typo3-typescript-sources 13.4.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/sync-and-publish.yml +265 -0
- package/.last-synced-tag +1 -0
- package/LICENSE.txt +339 -0
- package/README-TYPO3.md +166 -0
- package/README.md +28 -0
- package/adminpanel/admin-panel.ts +375 -0
- package/adminpanel/modules/cache.ts +27 -0
- package/adminpanel/modules/preview.ts +75 -0
- package/backend/action-button/abstract-action.ts +22 -0
- package/backend/action-button/deferred-action.ts +41 -0
- package/backend/action-button/immediate-action.ts +31 -0
- package/backend/action-dispatcher.ts +104 -0
- package/backend/ajax-data-handler/message-interface.ts +18 -0
- package/backend/ajax-data-handler/response-interface.ts +20 -0
- package/backend/ajax-data-handler.ts +214 -0
- package/backend/backend-exception.ts +22 -0
- package/backend/broadcast-message.ts +50 -0
- package/backend/broadcast-service.ts +52 -0
- package/backend/browse-database.ts +38 -0
- package/backend/clear-cache.ts +88 -0
- package/backend/clipboard-panel.ts +240 -0
- package/backend/close-current-window.ts +2 -0
- package/backend/code-editor/autocomplete/completion-result.ts +105 -0
- package/backend/code-editor/autocomplete/ts-code-completion.ts +142 -0
- package/backend/code-editor/autocomplete/ts-parser.ts +485 -0
- package/backend/code-editor/autocomplete/ts-ref.ts +164 -0
- package/backend/code-editor/element/code-mirror-element.ts +282 -0
- package/backend/code-editor/language/typoscript.ts +181 -0
- package/backend/code-editor/stream-parser/typoscript.ts +1600 -0
- package/backend/color-picker.ts +158 -0
- package/backend/color-scheme-switch.ts +179 -0
- package/backend/column-selector-button.ts +302 -0
- package/backend/context-help.ts +68 -0
- package/backend/context-menu-actions.ts +322 -0
- package/backend/context-menu.ts +751 -0
- package/backend/copy-to-clipboard.ts +79 -0
- package/backend/date-time-picker.ts +270 -0
- package/backend/document-save-actions.ts +159 -0
- package/backend/drag-tooltip.ts +285 -0
- package/backend/drag-uploader.ts +914 -0
- package/backend/element/alert-element.ts +116 -0
- package/backend/element/dispatch-modal-button.ts +50 -0
- package/backend/element/draggable-resizable-element.ts +249 -0
- package/backend/element/editable-page-title.ts +306 -0
- package/backend/element/icon-element.ts +84 -0
- package/backend/element/immediate-action-element.ts +89 -0
- package/backend/element/pagination.ts +59 -0
- package/backend/element/progress-bar-element.ts +172 -0
- package/backend/element/progress-tracker-element.ts +119 -0
- package/backend/element/pseudo-button.ts +58 -0
- package/backend/element/spinner-element.ts +51 -0
- package/backend/element/thumbnail-element.ts +80 -0
- package/backend/element-browser.ts +182 -0
- package/backend/enum/data-transfer-types.ts +21 -0
- package/backend/enum/icon-types.ts +31 -0
- package/backend/enum/key-types.ts +27 -0
- package/backend/enum/severity.ts +20 -0
- package/backend/enum/viewport/scaffold-identifier.ts +24 -0
- package/backend/event/client-request.ts +25 -0
- package/backend/event/consumable.ts +18 -0
- package/backend/event/consumer-scope.ts +54 -0
- package/backend/event/event-dispatcher.ts +26 -0
- package/backend/event/interaction-request-assignment.ts +24 -0
- package/backend/event/interaction-request-map.ts +75 -0
- package/backend/event/interaction-request.ts +48 -0
- package/backend/event/trigger-request.ts +56 -0
- package/backend/form/submit-interceptor.ts +66 -0
- package/backend/form-engine/container/files-control-container.ts +716 -0
- package/backend/form-engine/container/flex-form-container-container.ts +166 -0
- package/backend/form-engine/container/flex-form-section-container.ts +210 -0
- package/backend/form-engine/container/inline-control-container.ts +1230 -0
- package/backend/form-engine/container/site-language-container.ts +616 -0
- package/backend/form-engine/element/abstract-sortable-select-items.ts +186 -0
- package/backend/form-engine/element/category-element.ts +160 -0
- package/backend/form-engine/element/color-element.ts +81 -0
- package/backend/form-engine/element/datetime-element.ts +66 -0
- package/backend/form-engine/element/extra/char-counter.ts +112 -0
- package/backend/form-engine/element/extra/select-box-filter.ts +85 -0
- package/backend/form-engine/element/folder-element.ts +66 -0
- package/backend/form-engine/element/group-element.ts +47 -0
- package/backend/form-engine/element/json-element.ts +52 -0
- package/backend/form-engine/element/link-element.ts +121 -0
- package/backend/form-engine/element/mfa-info-element.ts +169 -0
- package/backend/form-engine/element/modifier/resizable.ts +27 -0
- package/backend/form-engine/element/modifier/tabbable.ts +29 -0
- package/backend/form-engine/element/online-media-form-element.ts +65 -0
- package/backend/form-engine/element/password-element.ts +71 -0
- package/backend/form-engine/element/select-multiple-side-by-side-element.ts +83 -0
- package/backend/form-engine/element/select-single-element.ts +82 -0
- package/backend/form-engine/element/select-tree-element.ts +148 -0
- package/backend/form-engine/element/select-tree-toolbar.ts +118 -0
- package/backend/form-engine/element/select-tree.ts +210 -0
- package/backend/form-engine/element/slug-element.ts +243 -0
- package/backend/form-engine/element/suggest/result-container.ts +118 -0
- package/backend/form-engine/element/suggest/result-item.ts +90 -0
- package/backend/form-engine/element/table-permission-element.ts +101 -0
- package/backend/form-engine/element/table-wizard-element.ts +427 -0
- package/backend/form-engine/element/text-element.ts +52 -0
- package/backend/form-engine/element/text-table-element.ts +31 -0
- package/backend/form-engine/field-control/add-record.ts +40 -0
- package/backend/form-engine/field-control/edit-popup.ts +64 -0
- package/backend/form-engine/field-control/insert-clipboard.ts +50 -0
- package/backend/form-engine/field-control/link-popup.ts +53 -0
- package/backend/form-engine/field-control/list-module.ts +40 -0
- package/backend/form-engine/field-control/password-generator.ts +102 -0
- package/backend/form-engine/field-control/reset-selection.ts +48 -0
- package/backend/form-engine/field-wizard/localization-state-selector.ts +67 -0
- package/backend/form-engine/field-wizard/value-picker.ts +123 -0
- package/backend/form-engine/field-wizard/value-slider.ts +86 -0
- package/backend/form-engine/inline-relation/ajax-dispatcher.ts +124 -0
- package/backend/form-engine/inline-relation/inline-response-interface.ts +41 -0
- package/backend/form-engine-link-browser-adapter.ts +129 -0
- package/backend/form-engine-review.ts +155 -0
- package/backend/form-engine-suggest.ts +133 -0
- package/backend/form-engine-validation.ts +686 -0
- package/backend/form-engine.ts +1391 -0
- package/backend/global-event-handler.ts +252 -0
- package/backend/grid-editor.ts +1077 -0
- package/backend/hashing/md5.ts +252 -0
- package/backend/helper.ts +24 -0
- package/backend/hotkeys/hotkey-storage.ts +63 -0
- package/backend/hotkeys.ts +216 -0
- package/backend/icons.ts +236 -0
- package/backend/image-manipulation.ts +885 -0
- package/backend/info-window.ts +46 -0
- package/backend/input/clearable.ts +128 -0
- package/backend/input/index.d.ts +8 -0
- package/backend/java-script-module-import-event-handler.ts +19 -0
- package/backend/key-bindings.ts +42 -0
- package/backend/layout-module/drag-drop.ts +359 -0
- package/backend/layout-module/paste.ts +165 -0
- package/backend/link-browser.ts +89 -0
- package/backend/live-search/element/backend-search.ts +34 -0
- package/backend/live-search/element/hint.ts +33 -0
- package/backend/live-search/element/provider/default-result-item.ts +52 -0
- package/backend/live-search/element/provider/page-provider-result-item.ts +52 -0
- package/backend/live-search/element/result/item/action/action-container.ts +135 -0
- package/backend/live-search/element/result/item/action/action.ts +56 -0
- package/backend/live-search/element/result/item/item-container.ts +224 -0
- package/backend/live-search/element/result/item/item.ts +74 -0
- package/backend/live-search/element/result/result-container.ts +110 -0
- package/backend/live-search/element/result/result-detail-container.ts +50 -0
- package/backend/live-search/element/result/result-pagination.ts +122 -0
- package/backend/live-search/element/search-option-item.ts +70 -0
- package/backend/live-search/live-search-configurator.ts +54 -0
- package/backend/live-search/live-search-shortcut.ts +29 -0
- package/backend/live-search/result-types/backend-module-result-type.ts +8 -0
- package/backend/live-search/result-types/default-result-type.ts +21 -0
- package/backend/live-search/result-types/page-result-type.ts +23 -0
- package/backend/localization.ts +390 -0
- package/backend/login-refresh.ts +525 -0
- package/backend/login.ts +179 -0
- package/backend/mail-link-handler.ts +45 -0
- package/backend/modal-interface.ts +19 -0
- package/backend/modal.ts +685 -0
- package/backend/module/iframe.ts +125 -0
- package/backend/module/router.ts +275 -0
- package/backend/module-menu.ts +550 -0
- package/backend/module.ts +133 -0
- package/backend/multi-record-selection-action.ts +44 -0
- package/backend/multi-record-selection-delete-action.ts +108 -0
- package/backend/multi-record-selection-edit-action.ts +56 -0
- package/backend/multi-record-selection.ts +468 -0
- package/backend/multi-step-wizard.ts +568 -0
- package/backend/new-content-element-wizard-button.ts +51 -0
- package/backend/new-multiple-pages.ts +108 -0
- package/backend/new-record-wizard.ts +680 -0
- package/backend/notification.ts +366 -0
- package/backend/offset.ts +40 -0
- package/backend/online-media.ts +110 -0
- package/backend/page-actions.ts +91 -0
- package/backend/page-link-handler.ts +51 -0
- package/backend/pagetsconfig/pagetsconfig-includes.ts +77 -0
- package/backend/popover.ts +165 -0
- package/backend/record-download-button.ts +104 -0
- package/backend/record-link-handler.ts +31 -0
- package/backend/record-search.ts +44 -0
- package/backend/recordlist.ts +230 -0
- package/backend/resource/resource.ts +35 -0
- package/backend/security/element/csp-reports.ts +406 -0
- package/backend/security/element/sudo-mode.ts +249 -0
- package/backend/security/sudo-mode-interceptor.ts +19 -0
- package/backend/settings/editor/editable-setting.ts +231 -0
- package/backend/settings/editor.ts +451 -0
- package/backend/settings/enum/settings-mode.enum.ts +24 -0
- package/backend/settings/type/base.ts +200 -0
- package/backend/settings/type/bool.ts +56 -0
- package/backend/settings/type/color.ts +64 -0
- package/backend/settings/type/int.ts +85 -0
- package/backend/settings/type/number.ts +61 -0
- package/backend/settings/type/page.ts +100 -0
- package/backend/settings/type/string.ts +77 -0
- package/backend/settings/type/stringlist.ts +87 -0
- package/backend/severity.ts +88 -0
- package/backend/site-inline-actions.ts +32 -0
- package/backend/sortable-table.ts +208 -0
- package/backend/storage/abstract-client-storage.ts +76 -0
- package/backend/storage/browser-session.ts +28 -0
- package/backend/storage/client.ts +28 -0
- package/backend/storage/module-state-storage.ts +118 -0
- package/backend/storage/persistent.ts +204 -0
- package/backend/switch-user.ts +82 -0
- package/backend/tabs.ts +72 -0
- package/backend/telephone-link-handler.ts +40 -0
- package/backend/tests/backend/storage/browser-storage-test.ts +87 -0
- package/backend/tests/backend/storage/client-test.ts +87 -0
- package/backend/tests/backend/utility/dom-helper-test.ts +51 -0
- package/backend/tests/backend-exception-test.ts +28 -0
- package/backend/tests/element/immediate-action-element-test.ts +81 -0
- package/backend/tests/form-engine-validation-test.ts +304 -0
- package/backend/tests/grid-editor-test.ts +29 -0
- package/backend/tests/hashing/md5Test.ts +28 -0
- package/backend/tests/icons-test.ts +23 -0
- package/backend/tests/notification-test.ts +161 -0
- package/backend/tests/popover-test.ts +83 -0
- package/backend/toolbar/clear-cache-menu.ts +88 -0
- package/backend/toolbar/live-search.ts +284 -0
- package/backend/toolbar/shortcut-menu.ts +254 -0
- package/backend/toolbar/system-information-menu.ts +161 -0
- package/backend/toolbar.ts +41 -0
- package/backend/tree/file-storage-browser.ts +194 -0
- package/backend/tree/file-storage-tree-container.ts +465 -0
- package/backend/tree/file-storage-tree.ts +42 -0
- package/backend/tree/page-browser.ts +272 -0
- package/backend/tree/page-tree-element.ts +602 -0
- package/backend/tree/page-tree.ts +152 -0
- package/backend/tree/tree-module-state.ts +159 -0
- package/backend/tree/tree-node-toggle.ts +31 -0
- package/backend/tree/tree-node.ts +97 -0
- package/backend/tree/tree-toolbar.ts +117 -0
- package/backend/tree/tree.ts +1595 -0
- package/backend/url-link-handler.ts +36 -0
- package/backend/user-pass-login.ts +255 -0
- package/backend/user-settings-manager.ts +189 -0
- package/backend/utility/collapse-state-persister.ts +205 -0
- package/backend/utility/collapse-state-search.ts +183 -0
- package/backend/utility/dom-helper.ts +91 -0
- package/backend/utility/drag-drop-utility.ts +47 -0
- package/backend/utility/message-utility.ts +45 -0
- package/backend/utility/top-level-module-import.ts +32 -0
- package/backend/utility.ts +194 -0
- package/backend/viewport/abstract-container.ts +22 -0
- package/backend/viewport/content-container.ts +98 -0
- package/backend/viewport/loader.ts +28 -0
- package/backend/viewport/navigation-container.ts +119 -0
- package/backend/viewport/resizable-navigation.ts +176 -0
- package/backend/viewport/toolbar.ts +27 -0
- package/backend/viewport/topbar.ts +39 -0
- package/backend/viewport.ts +46 -0
- package/backend/window-manager.ts +84 -0
- package/backend/wizard/move-content-element.ts +107 -0
- package/backend/wizard/move-page.ts +74 -0
- package/backend/wizard.ts +331 -0
- package/belog/backend-log.ts +88 -0
- package/beuser/backend-user-listing.ts +40 -0
- package/beuser/permissions.ts +291 -0
- package/core/ajax/ajax-request-types.ts +15 -0
- package/core/ajax/ajax-request.ts +202 -0
- package/core/ajax/ajax-response.ts +57 -0
- package/core/ajax/input-transformer.ts +92 -0
- package/core/ajax/simple-response-interface.ts +5 -0
- package/core/authentication/mfa-provider/totp.ts +54 -0
- package/core/cache/dedupe-async-task.ts +95 -0
- package/core/directive/markdown.ts +82 -0
- package/core/directive/nl2br.ts +16 -0
- package/core/document-service.ts +35 -0
- package/core/event/debounce-event.ts +40 -0
- package/core/event/event-interface.ts +24 -0
- package/core/event/regular-event.ts +58 -0
- package/core/event/request-animation-frame-event.ts +42 -0
- package/core/event/throttle-event.ts +54 -0
- package/core/java-script-item-handler.ts +29 -0
- package/core/java-script-item-processor.ts +171 -0
- package/core/lit-helper.ts +126 -0
- package/core/literals.ts +17 -0
- package/core/referrer-refresh.ts +2 -0
- package/core/security-utility.ts +89 -0
- package/core/tests/ajax/ajax-request-test.ts +290 -0
- package/core/tests/ajax/input-transformer-test.ts +64 -0
- package/core/tests/cache/dedupe-async-task-test.ts +152 -0
- package/core/tests/event/throttle-event-test.ts +47 -0
- package/core/tests/literals-test.ts +24 -0
- package/core/tests/security-utility-test.ts +50 -0
- package/core/utility/types.ts +9 -0
- package/dashboard/chart-initializer.ts +136 -0
- package/dashboard/dashboard.ts +1487 -0
- package/extensionmanager/distribution-image.ts +55 -0
- package/extensionmanager/main.ts +291 -0
- package/extensionmanager/repository.ts +195 -0
- package/extensionmanager/update.ts +118 -0
- package/extensionmanager/upload-form.ts +42 -0
- package/filelist/browse-files.ts +148 -0
- package/filelist/browse-folders.ts +94 -0
- package/filelist/context-menu-actions.ts +335 -0
- package/filelist/create-folder.ts +69 -0
- package/filelist/file-delete.ts +69 -0
- package/filelist/file-list-actions.ts +132 -0
- package/filelist/file-list-dragdrop.ts +139 -0
- package/filelist/file-list-rename-handler.ts +128 -0
- package/filelist/file-list-transfer-handler.ts +138 -0
- package/filelist/file-list.ts +396 -0
- package/filelist/file-replace.ts +37 -0
- package/filelist/linkbrowser-file-handler.ts +94 -0
- package/filelist/linkbrowser-folder-handler.ts +74 -0
- package/filelist/rename-file.ts +109 -0
- package/form/backend/form-editor/component/property-grid-editor.ts +340 -0
- package/form/backend/form-editor/core.ts +2104 -0
- package/form/backend/form-editor/helper.ts +226 -0
- package/form/backend/form-editor/inspector-component.ts +2323 -0
- package/form/backend/form-editor/mediator.ts +941 -0
- package/form/backend/form-editor/modals-component.ts +433 -0
- package/form/backend/form-editor/stage-component.ts +908 -0
- package/form/backend/form-editor/tree-component.ts +548 -0
- package/form/backend/form-editor/view-model.ts +1343 -0
- package/form/backend/form-editor.ts +846 -0
- package/form/backend/form-manager/main.ts +39 -0
- package/form/backend/form-manager/view-model.ts +789 -0
- package/form/backend/form-manager.ts +180 -0
- package/form/backend/helper.ts +60 -0
- package/form/frontend/date-picker.ts +38 -0
- package/frontend/default_frontend.ts +82 -0
- package/impexp/context-menu-actions.ts +50 -0
- package/impexp/import-export.ts +62 -0
- package/indexed-search/pagination.ts +26 -0
- package/indexed-search/statistics.ts +50 -0
- package/info/translation-status.ts +48 -0
- package/install/ajax/ajax-queue.ts +83 -0
- package/install/init-install.ts +2 -0
- package/install/init-installer.ts +2 -0
- package/install/install.ts +25 -0
- package/install/installer.ts +458 -0
- package/install/message-interface.ts +18 -0
- package/install/module/abstract-inline-module.ts +27 -0
- package/install/module/abstract-interactable-module.ts +107 -0
- package/install/module/environment/environment-check.ts +92 -0
- package/install/module/environment/folder-structure.ts +145 -0
- package/install/module/environment/image-processing.ts +141 -0
- package/install/module/environment/mail-test.ts +127 -0
- package/install/module/environment/php-info.ts +50 -0
- package/install/module/environment/system-information.ts +50 -0
- package/install/module/maintenance/cache.ts +59 -0
- package/install/module/maintenance/clear-tables.ts +134 -0
- package/install/module/maintenance/clear-typo3temp-files.ts +137 -0
- package/install/module/maintenance/create-admin.ts +126 -0
- package/install/module/maintenance/database-analyzer.ts +266 -0
- package/install/module/maintenance/dump-autoload.ts +58 -0
- package/install/module/maintenance/language-packs.ts +338 -0
- package/install/module/maintenance/reset-backend-user-uc.ts +58 -0
- package/install/module/password-strength.ts +56 -0
- package/install/module/settings/change-install-tool-password.ts +101 -0
- package/install/module/settings/extension-configuration.ts +224 -0
- package/install/module/settings/features.ts +102 -0
- package/install/module/settings/local-configuration.ts +316 -0
- package/install/module/settings/presets.ts +147 -0
- package/install/module/settings/system-maintainer.ts +111 -0
- package/install/module/upgrade/core-update.ts +255 -0
- package/install/module/upgrade/extension-compat-tester.ts +195 -0
- package/install/module/upgrade/extension-scanner.ts +381 -0
- package/install/module/upgrade/tca-ext-tables-check.ts +93 -0
- package/install/module/upgrade/tca-migrations-check.ts +101 -0
- package/install/module/upgrade/upgrade-docs.ts +310 -0
- package/install/module/upgrade/upgrade-wizards.ts +612 -0
- package/install/renderable/clearable.ts +113 -0
- package/install/renderable/flash-message.ts +64 -0
- package/install/renderable/info-box.ts +66 -0
- package/install/renderable/language-packs.ts +304 -0
- package/install/renderable/offset-group.ts +38 -0
- package/install/renderable/severity.ts +49 -0
- package/install/renderable/wrap-group.ts +36 -0
- package/install/router.ts +468 -0
- package/linkvalidator/linkvalidator-modal.ts +45 -0
- package/linkvalidator/linkvalidator.ts +101 -0
- package/lowlevel/query-generator.ts +132 -0
- package/lowlevel/reference-index.ts +44 -0
- package/opendocs/toolbar/opendocs-menu.ts +117 -0
- package/package.json +34 -0
- package/recycler/recycler.ts +539 -0
- package/redirects/event-handler.ts +108 -0
- package/redirects/form-engine-evaluation.ts +34 -0
- package/redirects/redirects-module.ts +58 -0
- package/rte-ckeditor/ckeditor5.ts +402 -0
- package/rte-ckeditor/css-prefixer.ts +94 -0
- package/rte-ckeditor/legacy/ckeditor5-bundle.ts +17 -0
- package/rte-ckeditor/legacy/ckeditor5-inspector.ts +2 -0
- package/rte-ckeditor/plugin/typo3-link.ts +810 -0
- package/rte-ckeditor/plugin/whitespace.ts +114 -0
- package/rte-ckeditor/rte-link-browser.ts +112 -0
- package/rte-ckeditor/tests/css-prefixer-test.ts +314 -0
- package/scheduler/scheduler-add-group.ts +119 -0
- package/scheduler/scheduler-editable-group-name.ts +307 -0
- package/scheduler/scheduler-sortable-groups.ts +59 -0
- package/scheduler/scheduler.ts +466 -0
- package/setup/setup-module.ts +122 -0
- package/styleguide/checkbox-demo.ts +5 -0
- package/styleguide/element/theme-switcher-element.ts +101 -0
- package/styleguide/filter.ts +22 -0
- package/styleguide/find-icons.ts +78 -0
- package/styleguide/processing-indicator.ts +78 -0
- package/styleguide/render-notifications.ts +64 -0
- package/sys-note/element/delete-button.ts +78 -0
- package/tstemplate/constant-editor.ts +64 -0
- package/tstemplate/information-module.ts +31 -0
- package/tstemplate/template-analyzer.ts +77 -0
- package/viewpage/main.ts +253 -0
- package/workspaces/backend.ts +979 -0
- package/workspaces/preview.ts +232 -0
- package/workspaces/renderable/comment-view.ts +79 -0
- package/workspaces/renderable/diff-view.ts +58 -0
- package/workspaces/renderable/history-view.ts +97 -0
- package/workspaces/renderable/record-information.ts +118 -0
- package/workspaces/renderable/record-table.ts +355 -0
- package/workspaces/renderable/send-to-stage-form.ts +108 -0
- package/workspaces/toolbar/workspaces-menu.ts +190 -0
- package/workspaces/utility/icon-helper.ts +57 -0
- package/workspaces/workspaces.ts +136 -0
|
@@ -0,0 +1,550 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of the TYPO3 CMS project.
|
|
3
|
+
*
|
|
4
|
+
* It is free software; you can redistribute it and/or modify it under
|
|
5
|
+
* the terms of the GNU General Public License, either version 2
|
|
6
|
+
* of the License, or any later version.
|
|
7
|
+
*
|
|
8
|
+
* For the full copyright and license information, please read the
|
|
9
|
+
* LICENSE.txt file that was distributed with this source code.
|
|
10
|
+
*
|
|
11
|
+
* The TYPO3 project - inspiring people to share!
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import type { AjaxResponse } from '@typo3/core/ajax/ajax-response';
|
|
15
|
+
import { ScaffoldIdentifierEnum } from './enum/viewport/scaffold-identifier';
|
|
16
|
+
import { flushModuleCache, type Module, ModuleSelector, type ModuleState, ModuleUtility } from '@typo3/backend/module';
|
|
17
|
+
import PersistentStorage from './storage/persistent';
|
|
18
|
+
import Viewport from './viewport';
|
|
19
|
+
import ClientRequest from './event/client-request';
|
|
20
|
+
import TriggerRequest from './event/trigger-request';
|
|
21
|
+
import type InteractionRequest from './event/interaction-request';
|
|
22
|
+
import AjaxRequest from '@typo3/core/ajax/ajax-request';
|
|
23
|
+
import RegularEvent from '@typo3/core/event/regular-event';
|
|
24
|
+
import { ModuleStateStorage } from './storage/module-state-storage';
|
|
25
|
+
import { selector } from '@typo3/core/literals';
|
|
26
|
+
import DocumentService from '@typo3/core/document-service';
|
|
27
|
+
import { Collapse } from 'bootstrap';
|
|
28
|
+
import { KeyTypesEnum } from '@typo3/backend/enum/key-types';
|
|
29
|
+
|
|
30
|
+
enum ModuleMenuSelector {
|
|
31
|
+
menu = '[data-modulemenu]',
|
|
32
|
+
item = '[data-modulemenu-identifier]',
|
|
33
|
+
collapsible = '[data-modulemenu-collapsible="true"]',
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
interface ModuleMenuItem {
|
|
37
|
+
identifier: string,
|
|
38
|
+
collapsible: boolean,
|
|
39
|
+
expanded: boolean,
|
|
40
|
+
level: number | null,
|
|
41
|
+
element: HTMLElement
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Class to render the module menu and handle the BE navigation
|
|
46
|
+
* Module: @typo3/backend/module-menu
|
|
47
|
+
*/
|
|
48
|
+
class ModuleMenu {
|
|
49
|
+
private loadedModule: string = null;
|
|
50
|
+
|
|
51
|
+
constructor() {
|
|
52
|
+
DocumentService.ready().then((): void => {
|
|
53
|
+
this.initialize();
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
private static getModuleMenuItemFromElement(element: HTMLElement): ModuleMenuItem {
|
|
58
|
+
const item: ModuleMenuItem = {
|
|
59
|
+
identifier: element.dataset.modulemenuIdentifier,
|
|
60
|
+
level: element.parentElement.dataset.modulemenuLevel ? parseInt(element.parentElement.dataset.modulemenuLevel, 10) : null,
|
|
61
|
+
collapsible: element.dataset.modulemenuCollapsible === 'true',
|
|
62
|
+
expanded: element.attributes.getNamedItem('aria-expanded')?.value === 'true',
|
|
63
|
+
element: element,
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
return item;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Fetches all module menu elements in the local storage that should be collapsed
|
|
71
|
+
*
|
|
72
|
+
* @returns {Object}
|
|
73
|
+
*/
|
|
74
|
+
private static getCollapsedMainMenuItems(): { [key: string]: boolean } {
|
|
75
|
+
if (PersistentStorage.isset('modulemenu')) {
|
|
76
|
+
return JSON.parse(PersistentStorage.get('modulemenu'));
|
|
77
|
+
} else {
|
|
78
|
+
return {};
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Adds a module menu item to the local storage
|
|
84
|
+
*
|
|
85
|
+
* @param {string} item
|
|
86
|
+
*/
|
|
87
|
+
private static addCollapsedMainMenuItem(item: string): void {
|
|
88
|
+
const existingItems = ModuleMenu.getCollapsedMainMenuItems();
|
|
89
|
+
existingItems[item] = true;
|
|
90
|
+
PersistentStorage.set('modulemenu', JSON.stringify(existingItems));
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Removes a module menu item from the local storage
|
|
95
|
+
*
|
|
96
|
+
* @param {string} item
|
|
97
|
+
*/
|
|
98
|
+
private static removeCollapseMainMenuItem(item: string): void {
|
|
99
|
+
const existingItems = this.getCollapsedMainMenuItems();
|
|
100
|
+
delete existingItems[item];
|
|
101
|
+
PersistentStorage.set('modulemenu', JSON.stringify(existingItems));
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Prepends previously saved record id to the url params
|
|
106
|
+
*
|
|
107
|
+
* @param {Object} moduleData
|
|
108
|
+
* @param {string} params query string parameters for module url
|
|
109
|
+
* @return {string}
|
|
110
|
+
*/
|
|
111
|
+
private static includeId(moduleData: Module, params: string): string {
|
|
112
|
+
if (!moduleData.navigationComponentId) {
|
|
113
|
+
return params;
|
|
114
|
+
}
|
|
115
|
+
// get id
|
|
116
|
+
let section = '';
|
|
117
|
+
if (moduleData.navigationComponentId === '@typo3/backend/tree/page-tree-element') {
|
|
118
|
+
section = 'web';
|
|
119
|
+
} else {
|
|
120
|
+
section = moduleData.name.split('_')[0];
|
|
121
|
+
}
|
|
122
|
+
const moduleStateStorage = ModuleStateStorage.current(section);
|
|
123
|
+
if (moduleStateStorage.identifier) {
|
|
124
|
+
params = 'id=' + encodeURIComponent(moduleStateStorage.identifier) + '&' + params;
|
|
125
|
+
}
|
|
126
|
+
return params;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
private static toggleMenu(collapse?: boolean): void {
|
|
130
|
+
const scaffold = document.querySelector(ScaffoldIdentifierEnum.scaffold);
|
|
131
|
+
const expandedClass = 'scaffold-modulemenu-expanded';
|
|
132
|
+
|
|
133
|
+
if (typeof collapse === 'undefined') {
|
|
134
|
+
collapse = scaffold.classList.contains(expandedClass);
|
|
135
|
+
}
|
|
136
|
+
scaffold.classList.toggle(expandedClass, !collapse);
|
|
137
|
+
|
|
138
|
+
if (!collapse) {
|
|
139
|
+
scaffold.classList.remove('scaffold-toolbar-expanded');
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Persist collapsed state in the UC of the current user
|
|
143
|
+
PersistentStorage.set(
|
|
144
|
+
'BackendComponents.States.typo3-module-menu',
|
|
145
|
+
{
|
|
146
|
+
collapsed: collapse,
|
|
147
|
+
},
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
private static toggleModuleGroup(element: HTMLElement, expand?: boolean): void {
|
|
152
|
+
const menuItem = ModuleMenu.getModuleMenuItemFromElement(element);
|
|
153
|
+
const moduleGroup = menuItem.element.closest('.modulemenu-group');
|
|
154
|
+
const moduleGroupContainer = moduleGroup.querySelector('.modulemenu-group-container');
|
|
155
|
+
const collapseInstance = Collapse.getOrCreateInstance(moduleGroupContainer, {
|
|
156
|
+
toggle: false // Do not auto-toggle on init.
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
if (expand === undefined) {
|
|
160
|
+
// No intended state given: toggle state.
|
|
161
|
+
expand = !menuItem.expanded;
|
|
162
|
+
} else if (expand === menuItem.expanded) {
|
|
163
|
+
// Intended state is already reached.
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (!expand) {
|
|
168
|
+
ModuleMenu.addCollapsedMainMenuItem(menuItem.identifier);
|
|
169
|
+
collapseInstance.hide();
|
|
170
|
+
} else {
|
|
171
|
+
ModuleMenu.removeCollapseMainMenuItem(menuItem.identifier);
|
|
172
|
+
collapseInstance.show();
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
moduleGroup.classList.toggle('modulemenu-group-collapsed', !expand);
|
|
176
|
+
moduleGroup.classList.toggle('modulemenu-group-expanded', expand);
|
|
177
|
+
|
|
178
|
+
element.setAttribute('aria-expanded', (expand).toString());
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
private static highlightModule(identifier: string): void {
|
|
182
|
+
// Handle modulemenu
|
|
183
|
+
const menu = document.querySelector(ModuleMenuSelector.menu);
|
|
184
|
+
menu.querySelectorAll(ModuleMenuSelector.item).forEach((element: Element) => {
|
|
185
|
+
element.classList.remove('modulemenu-action-active');
|
|
186
|
+
element.removeAttribute('aria-current');
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
// Handle toolbar
|
|
190
|
+
//
|
|
191
|
+
// This is a workaround, to ensure the toolbar module links are handled.
|
|
192
|
+
// There is no dedicated module rendering in the toolbar, so we rely on this
|
|
193
|
+
// workaround until this changes. Even the code matches the handling of
|
|
194
|
+
// module-menu-items we keep this separate to show the problem here.
|
|
195
|
+
const toolbar = document.querySelector('.t3js-scaffold-toolbar');
|
|
196
|
+
toolbar.querySelectorAll(ModuleSelector.link + '.dropdown-item').forEach((element: Element) => {
|
|
197
|
+
element.classList.remove('active');
|
|
198
|
+
element.removeAttribute('aria-current');
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
const module = ModuleUtility.getFromName(identifier);
|
|
202
|
+
this.highlightModuleMenuItem(module, true);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
private static highlightModuleMenuItem(module: Module, current: boolean = true): void {
|
|
206
|
+
// Handle modulemenu
|
|
207
|
+
const menu = document.querySelector(ModuleMenuSelector.menu);
|
|
208
|
+
const menuElements = menu.querySelectorAll(ModuleMenuSelector.item + selector`[data-modulemenu-identifier="${module.name}"]`);
|
|
209
|
+
menuElements.forEach((element: HTMLElement) => {
|
|
210
|
+
element.classList.add('modulemenu-action-active');
|
|
211
|
+
if (current) {
|
|
212
|
+
element.setAttribute('aria-current', 'location');
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
// Handle toolbar
|
|
217
|
+
//
|
|
218
|
+
// This is a workaround, to ensure the toolbar module links are handled.
|
|
219
|
+
// There is no dedicated module rendering in the toolbar, so we rely on this
|
|
220
|
+
// workaround until this changes. Even the code matches the handling of
|
|
221
|
+
// module-menu-items we keep this separate to show the problem here.
|
|
222
|
+
const toolbar = document.querySelector('.t3js-scaffold-toolbar');
|
|
223
|
+
const toolbarElements = toolbar.querySelectorAll(ModuleSelector.link + selector`[data-moduleroute-identifier="${module.name}"].dropdown-item`);
|
|
224
|
+
toolbarElements.forEach((element: HTMLElement) => {
|
|
225
|
+
element.classList.add('active');
|
|
226
|
+
if (current) {
|
|
227
|
+
element.setAttribute('aria-current', 'location');
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
if (menuElements.length > 0 || toolbarElements.length > 0) {
|
|
232
|
+
current = false;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
if (module.parent !== '') {
|
|
236
|
+
this.highlightModuleMenuItem(ModuleUtility.getFromName(module.parent), current);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
private static getPreviousItem(item: HTMLElement): HTMLElement {
|
|
241
|
+
const previousParent = item.parentElement.previousElementSibling; // previous <li>
|
|
242
|
+
if (previousParent === null) {
|
|
243
|
+
return ModuleMenu.getLastItem(item);
|
|
244
|
+
}
|
|
245
|
+
return previousParent.firstElementChild as HTMLElement; // the <element>
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
private static getNextItem(item: HTMLElement): HTMLElement {
|
|
249
|
+
const nextParent = item.parentElement.nextElementSibling; // next <li>
|
|
250
|
+
if (nextParent === null) {
|
|
251
|
+
return ModuleMenu.getFirstItem(item);
|
|
252
|
+
}
|
|
253
|
+
return nextParent.firstElementChild as HTMLElement; // the <element>
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
private static getFirstItem(item: HTMLElement): HTMLElement {
|
|
257
|
+
// from <element> up to <ul> and down to <element> of first <li>
|
|
258
|
+
return item.parentElement.parentElement.firstElementChild.firstElementChild as HTMLElement;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
private static getLastItem(item: HTMLElement): HTMLElement {
|
|
262
|
+
// from <element> up to <ul> and down to <element> of first <li>
|
|
263
|
+
return item.parentElement.parentElement.lastElementChild.firstElementChild as HTMLElement;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
private static getParentItem(item: HTMLElement): HTMLElement {
|
|
267
|
+
// from <element> up to <ul> and the <li> above and down down its <element>
|
|
268
|
+
return item.parentElement.parentElement.parentElement.firstElementChild as HTMLElement;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
private static getFirstChildItem(item: HTMLElement): HTMLElement {
|
|
272
|
+
// the first <li> of the <ul> following the <element>, then down down its <element>
|
|
273
|
+
return item.nextElementSibling.firstElementChild.firstElementChild as HTMLElement;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Refresh the HTML by fetching the menu again
|
|
278
|
+
*/
|
|
279
|
+
public refreshMenu(): Promise<void> {
|
|
280
|
+
return new AjaxRequest(TYPO3.settings.ajaxUrls.modulemenu).get().then(async (response: AjaxResponse): Promise<void> => {
|
|
281
|
+
const result = await response.resolve();
|
|
282
|
+
document.getElementById('modulemenu').outerHTML = result.menu;
|
|
283
|
+
flushModuleCache();
|
|
284
|
+
this.initializeModuleMenuEvents();
|
|
285
|
+
if (this.loadedModule) {
|
|
286
|
+
ModuleMenu.highlightModule(this.loadedModule);
|
|
287
|
+
}
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
public getCurrentModule(): string | null {
|
|
292
|
+
return this.loadedModule;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Reloads the frames
|
|
297
|
+
*
|
|
298
|
+
* Hint: This method can't be static (yet), as this must be bound to the ModuleMenu instance.
|
|
299
|
+
*/
|
|
300
|
+
public reloadFrames(): void {
|
|
301
|
+
Viewport.ContentContainer.refresh();
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Event handler called after clicking on the module menu item
|
|
306
|
+
*/
|
|
307
|
+
public showModule(name: string, params?: string, event: Event = null): Promise<void> {
|
|
308
|
+
params = params || '';
|
|
309
|
+
const moduleData = ModuleUtility.getFromName(name);
|
|
310
|
+
return this.loadModuleComponents(
|
|
311
|
+
moduleData,
|
|
312
|
+
params,
|
|
313
|
+
new ClientRequest('typo3.showModule', event),
|
|
314
|
+
);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
private initialize(): void {
|
|
318
|
+
if (document.querySelector(ModuleMenuSelector.menu) === null) {
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
this.initializeModuleMenuEvents();
|
|
323
|
+
Viewport.Topbar.Toolbar.registerEvent(() => {
|
|
324
|
+
// Only initialize top bar events when top bar exists.
|
|
325
|
+
// E.g. install tool has no top bar
|
|
326
|
+
if (document.querySelector('.t3js-scaffold-toolbar')) {
|
|
327
|
+
this.initializeTopBarEvents();
|
|
328
|
+
}
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* Implement the complete keyboard navigation of the menus
|
|
334
|
+
*/
|
|
335
|
+
private keyboardNavigation(event: KeyboardEvent, target: HTMLElement): void {
|
|
336
|
+
const menuItem = ModuleMenu.getModuleMenuItemFromElement(target);
|
|
337
|
+
let item = null;
|
|
338
|
+
|
|
339
|
+
switch (event.key) {
|
|
340
|
+
case KeyTypesEnum.UP:
|
|
341
|
+
item = ModuleMenu.getPreviousItem(menuItem.element);
|
|
342
|
+
break;
|
|
343
|
+
case KeyTypesEnum.DOWN:
|
|
344
|
+
item = ModuleMenu.getNextItem(menuItem.element);
|
|
345
|
+
break;
|
|
346
|
+
case KeyTypesEnum.LEFT:
|
|
347
|
+
if (menuItem.collapsible) {
|
|
348
|
+
ModuleMenu.toggleModuleGroup(menuItem.element, false);
|
|
349
|
+
}
|
|
350
|
+
if (menuItem.level > 1) {
|
|
351
|
+
item = ModuleMenu.getParentItem(menuItem.element);
|
|
352
|
+
}
|
|
353
|
+
break;
|
|
354
|
+
case KeyTypesEnum.RIGHT:
|
|
355
|
+
if (menuItem.collapsible) {
|
|
356
|
+
ModuleMenu.toggleModuleGroup(menuItem.element, true);
|
|
357
|
+
item = ModuleMenu.getFirstChildItem(menuItem.element);
|
|
358
|
+
}
|
|
359
|
+
break;
|
|
360
|
+
case KeyTypesEnum.HOME:
|
|
361
|
+
if (event.ctrlKey && menuItem.level > 1) {
|
|
362
|
+
item = document.querySelector(ModuleMenuSelector.menu + ' ' + ModuleMenuSelector.item) as HTMLElement;
|
|
363
|
+
break;
|
|
364
|
+
}
|
|
365
|
+
item = ModuleMenu.getFirstItem(menuItem.element);
|
|
366
|
+
break;
|
|
367
|
+
case KeyTypesEnum.END:
|
|
368
|
+
if (event.ctrlKey && menuItem.level > 1) {
|
|
369
|
+
item = ModuleMenu.getLastItem(document.querySelector(ModuleMenuSelector.menu + ' ' + ModuleMenuSelector.item));
|
|
370
|
+
} else {
|
|
371
|
+
item = ModuleMenu.getLastItem(menuItem.element);
|
|
372
|
+
}
|
|
373
|
+
break;
|
|
374
|
+
case KeyTypesEnum.SPACE:
|
|
375
|
+
case KeyTypesEnum.ENTER:
|
|
376
|
+
// we do not want the click handler to run, need to prevent default immediately
|
|
377
|
+
event.preventDefault();
|
|
378
|
+
|
|
379
|
+
if (event.repeat) {
|
|
380
|
+
// Ignore repeated event invocation
|
|
381
|
+
break;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
if (menuItem.collapsible) {
|
|
385
|
+
// Always select the first element of sub-menu on ENTER/SPACE. Open sub-menu if necessary.
|
|
386
|
+
ModuleMenu.toggleModuleGroup(menuItem.element, true);
|
|
387
|
+
item = ModuleMenu.getFirstChildItem(menuItem.element);
|
|
388
|
+
} else {
|
|
389
|
+
menuItem.element.click();
|
|
390
|
+
}
|
|
391
|
+
break;
|
|
392
|
+
case KeyTypesEnum.ESCAPE:
|
|
393
|
+
// Close sub-menu on ESCAPE either from inside sub-menu or when trigger-button is focused.
|
|
394
|
+
if (menuItem.level > 1) {
|
|
395
|
+
item = ModuleMenu.getParentItem(menuItem.element);
|
|
396
|
+
} else if (menuItem.level === 1 && menuItem.collapsible) {
|
|
397
|
+
item = menuItem.element;
|
|
398
|
+
}
|
|
399
|
+
if (item !== null) {
|
|
400
|
+
ModuleMenu.toggleModuleGroup(item, false);
|
|
401
|
+
}
|
|
402
|
+
break;
|
|
403
|
+
default:
|
|
404
|
+
item = null;
|
|
405
|
+
}
|
|
406
|
+
if (item !== null) {
|
|
407
|
+
// Disable additional scrolling e.g. triggered by arrow-keypress.
|
|
408
|
+
event.preventDefault();
|
|
409
|
+
item.focus();
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
private initializeModuleMenuEvents(): void {
|
|
414
|
+
const moduleMenu = document.querySelector(ModuleMenuSelector.menu);
|
|
415
|
+
|
|
416
|
+
new RegularEvent('keydown', this.keyboardNavigation)
|
|
417
|
+
.delegateTo(moduleMenu, ModuleMenuSelector.item);
|
|
418
|
+
|
|
419
|
+
new RegularEvent('click', (event: Event, target: HTMLElement): void => {
|
|
420
|
+
event.preventDefault();
|
|
421
|
+
const moduleRoute = ModuleUtility.getRouteFromElement(target);
|
|
422
|
+
this.showModule(moduleRoute.identifier, moduleRoute.params, event);
|
|
423
|
+
}).delegateTo(moduleMenu, ModuleSelector.link);
|
|
424
|
+
|
|
425
|
+
new RegularEvent('click', (event: Event, target: HTMLElement): void => {
|
|
426
|
+
event.preventDefault();
|
|
427
|
+
ModuleMenu.toggleModuleGroup(target);
|
|
428
|
+
}).delegateTo(moduleMenu, ModuleMenuSelector.collapsible);
|
|
429
|
+
|
|
430
|
+
new RegularEvent('shown.bs.collapse', (event: Event, target: HTMLElement): void => {
|
|
431
|
+
// Wait for collapsible to become fully visible, then scroll module-group into view if necessary.
|
|
432
|
+
target.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'start' });
|
|
433
|
+
}).delegateTo(moduleMenu, '.modulemenu-group');
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
* Initialize events for label toggle and help menu
|
|
438
|
+
*/
|
|
439
|
+
private initializeTopBarEvents(): void {
|
|
440
|
+
const toolbar = document.querySelector('.t3js-scaffold-toolbar');
|
|
441
|
+
|
|
442
|
+
new RegularEvent('click', (event: Event, target: HTMLElement): void => {
|
|
443
|
+
event.preventDefault();
|
|
444
|
+
const moduleRoute = ModuleUtility.getRouteFromElement(target);
|
|
445
|
+
this.showModule(moduleRoute.identifier, moduleRoute.params, event);
|
|
446
|
+
}).delegateTo(toolbar, ModuleSelector.link);
|
|
447
|
+
|
|
448
|
+
new RegularEvent('click', (e: Event): void => {
|
|
449
|
+
e.preventDefault();
|
|
450
|
+
ModuleMenu.toggleMenu();
|
|
451
|
+
}).bindTo(document.querySelector('.t3js-topbar-button-modulemenu'));
|
|
452
|
+
|
|
453
|
+
new RegularEvent('click', (e: Event): void => {
|
|
454
|
+
e.preventDefault();
|
|
455
|
+
ModuleMenu.toggleMenu(true);
|
|
456
|
+
}).bindTo(document.querySelector('.t3js-scaffold-content-overlay'));
|
|
457
|
+
|
|
458
|
+
const moduleLoadListener = (evt: CustomEvent<ModuleState>) => {
|
|
459
|
+
const moduleName = evt.detail.module;
|
|
460
|
+
if (!moduleName || this.loadedModule === moduleName) {
|
|
461
|
+
return;
|
|
462
|
+
}
|
|
463
|
+
const moduleData = ModuleUtility.getFromName(moduleName);
|
|
464
|
+
if (!moduleData.link) {
|
|
465
|
+
return;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
ModuleMenu.highlightModule(moduleName);
|
|
469
|
+
this.loadedModule = moduleName;
|
|
470
|
+
|
|
471
|
+
// Synchronise navigation container if module is a standalone module (linked via ModuleMenu).
|
|
472
|
+
// Do not hide navigation for intermediate modules like record_edit, which may be used
|
|
473
|
+
// with our without a navigation component, depending on the context.
|
|
474
|
+
if (moduleData.navigationComponentId) {
|
|
475
|
+
Viewport.NavigationContainer.showComponent(moduleData.navigationComponentId);
|
|
476
|
+
} else {
|
|
477
|
+
Viewport.NavigationContainer.hide();
|
|
478
|
+
}
|
|
479
|
+
};
|
|
480
|
+
document.addEventListener('typo3-module-load', moduleLoadListener);
|
|
481
|
+
document.addEventListener('typo3-module-loaded', moduleLoadListener);
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
/**
|
|
485
|
+
* Shows requested module (e.g. list/page)
|
|
486
|
+
*/
|
|
487
|
+
private loadModuleComponents(
|
|
488
|
+
moduleData: Module,
|
|
489
|
+
params: string,
|
|
490
|
+
interactionRequest: InteractionRequest,
|
|
491
|
+
): Promise<void> {
|
|
492
|
+
const moduleName = moduleData.name;
|
|
493
|
+
|
|
494
|
+
// Allow other components e.g. Formengine to cancel switching between modules
|
|
495
|
+
// (e.g. you have unsaved changes in the form)
|
|
496
|
+
const promise = Viewport.ContentContainer.beforeSetUrl(interactionRequest);
|
|
497
|
+
promise.then((): void => {
|
|
498
|
+
if (moduleData.navigationComponentId) {
|
|
499
|
+
Viewport.NavigationContainer.showComponent(moduleData.navigationComponentId);
|
|
500
|
+
} else {
|
|
501
|
+
Viewport.NavigationContainer.hide();
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
ModuleMenu.highlightModule(moduleName);
|
|
505
|
+
this.loadedModule = moduleName;
|
|
506
|
+
params = ModuleMenu.includeId(moduleData, params);
|
|
507
|
+
this.openInContentContainer(
|
|
508
|
+
moduleName,
|
|
509
|
+
moduleData.link,
|
|
510
|
+
params,
|
|
511
|
+
new TriggerRequest(
|
|
512
|
+
'typo3.loadModuleComponents',
|
|
513
|
+
interactionRequest,
|
|
514
|
+
),
|
|
515
|
+
);
|
|
516
|
+
});
|
|
517
|
+
return promise;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
private openInContentContainer(
|
|
521
|
+
module: string,
|
|
522
|
+
url: string,
|
|
523
|
+
params: string,
|
|
524
|
+
interactionRequest: InteractionRequest
|
|
525
|
+
): Promise<void> {
|
|
526
|
+
const urlToLoad = url + (params ? (url.includes('?') ? '&' : '?') + params : '');
|
|
527
|
+
return Viewport.ContentContainer.setUrl(
|
|
528
|
+
urlToLoad,
|
|
529
|
+
new TriggerRequest('typo3.openInContentFrame', interactionRequest),
|
|
530
|
+
module
|
|
531
|
+
);
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
interface ModuleMenuNamespace {
|
|
536
|
+
App: ModuleMenu;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
let moduleMenuApp: ModuleMenuNamespace = top?.TYPO3?.ModuleMenu;
|
|
540
|
+
|
|
541
|
+
if (!moduleMenuApp) {
|
|
542
|
+
moduleMenuApp = {
|
|
543
|
+
App: new ModuleMenu(),
|
|
544
|
+
};
|
|
545
|
+
if (top.TYPO3 !== undefined) {
|
|
546
|
+
top.TYPO3.ModuleMenu = moduleMenuApp;
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
export default moduleMenuApp;
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of the TYPO3 CMS project.
|
|
3
|
+
*
|
|
4
|
+
* It is free software; you can redistribute it and/or modify it under
|
|
5
|
+
* the terms of the GNU General Public License, either version 2
|
|
6
|
+
* of the License, or any later version.
|
|
7
|
+
*
|
|
8
|
+
* For the full copyright and license information, please read the
|
|
9
|
+
* LICENSE.txt file that was distributed with this source code.
|
|
10
|
+
*
|
|
11
|
+
* The TYPO3 project - inspiring people to share!
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Module: @typo3/backend/module
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
export interface ModuleState {
|
|
19
|
+
url: string;
|
|
20
|
+
title?: string | null;
|
|
21
|
+
module?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @internal
|
|
26
|
+
*/
|
|
27
|
+
export interface Module {
|
|
28
|
+
name: string;
|
|
29
|
+
aliases: Array<string>;
|
|
30
|
+
component: string;
|
|
31
|
+
navigationComponentId: string;
|
|
32
|
+
parent: string;
|
|
33
|
+
link: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @internal
|
|
38
|
+
*/
|
|
39
|
+
export enum ModuleSelector {
|
|
40
|
+
link = '[data-moduleroute-identifier]'
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* @internal
|
|
45
|
+
*/
|
|
46
|
+
export interface ModuleRoute {
|
|
47
|
+
identifier: string;
|
|
48
|
+
params: string | null;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* @internal
|
|
53
|
+
*/
|
|
54
|
+
export class ModuleUtility {
|
|
55
|
+
public static getRouteFromElement(element: HTMLElement): ModuleRoute {
|
|
56
|
+
const moduleRoute: ModuleRoute = {
|
|
57
|
+
identifier: element.dataset.modulerouteIdentifier,
|
|
58
|
+
params: element.dataset.modulerouteParams
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
return moduleRoute;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Gets the module properties from module information data attribute
|
|
66
|
+
*/
|
|
67
|
+
public static getFromName(name: string): Module {
|
|
68
|
+
const parsedRecord = getParsedRecordFromName(name);
|
|
69
|
+
if (parsedRecord === null) {
|
|
70
|
+
return {
|
|
71
|
+
name: name,
|
|
72
|
+
aliases: [],
|
|
73
|
+
component: '',
|
|
74
|
+
navigationComponentId: '',
|
|
75
|
+
parent: '',
|
|
76
|
+
link: ''
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
name: name,
|
|
81
|
+
aliases: parsedRecord.aliases || [],
|
|
82
|
+
component: parsedRecord.component || '',
|
|
83
|
+
navigationComponentId: parsedRecord.navigationComponentId || '',
|
|
84
|
+
parent: parsedRecord.parent || '',
|
|
85
|
+
link: parsedRecord.link || '',
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
interface ParsedInformation {
|
|
91
|
+
[index: string]: Partial<Module>;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Runtime cache of json serialized module information
|
|
96
|
+
*/
|
|
97
|
+
let parsedInformation: ParsedInformation = null;
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Flushes the runtime cache containing parsed module information
|
|
101
|
+
*
|
|
102
|
+
* @internal
|
|
103
|
+
*/
|
|
104
|
+
export function flushModuleCache(): void {
|
|
105
|
+
parsedInformation = null;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function getParsedInformation(): ParsedInformation|null {
|
|
109
|
+
if (parsedInformation === null) {
|
|
110
|
+
const modulesInformation: string = String((document.querySelector('[data-modulemenu]') as HTMLElement)?.dataset.modulesInformation || '');
|
|
111
|
+
if (modulesInformation !== '') {
|
|
112
|
+
try {
|
|
113
|
+
parsedInformation = JSON.parse(modulesInformation);
|
|
114
|
+
} catch {
|
|
115
|
+
console.error('Invalid modules information provided.');
|
|
116
|
+
parsedInformation = null;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return parsedInformation;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function getParsedRecordFromName(name: string): Partial<Module>|null {
|
|
124
|
+
const parsedModuleInformation: ParsedInformation = getParsedInformation();
|
|
125
|
+
if (parsedModuleInformation !== null) {
|
|
126
|
+
for (const [key, module] of Object.entries(parsedModuleInformation)) {
|
|
127
|
+
if (name === key || module.aliases.includes(name)) {
|
|
128
|
+
return parsedModuleInformation[key];
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return null;
|
|
133
|
+
}
|