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,254 @@
|
|
|
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 AjaxRequest from '@typo3/core/ajax/ajax-request';
|
|
15
|
+
import Icons from '../icons';
|
|
16
|
+
import Modal from '../modal';
|
|
17
|
+
import Notification from '../notification';
|
|
18
|
+
import Viewport from '../viewport';
|
|
19
|
+
import SecurityUtility from '@typo3/core/security-utility';
|
|
20
|
+
import '@typo3/backend/element/spinner-element';
|
|
21
|
+
import { Sizes } from '../enum/icon-types';
|
|
22
|
+
import RegularEvent from '@typo3/core/event/regular-event';
|
|
23
|
+
import type { AjaxResponse } from '@typo3/core/ajax/ajax-response';
|
|
24
|
+
|
|
25
|
+
enum Identifiers {
|
|
26
|
+
containerSelector = '#typo3-cms-backend-backend-toolbaritems-shortcuttoolbaritem',
|
|
27
|
+
toolbarIconSelector = '.dropdown-toggle span.icon',
|
|
28
|
+
toolbarMenuSelector = '.dropdown-menu',
|
|
29
|
+
|
|
30
|
+
shortcutItemSelector = '.t3js-topbar-shortcut',
|
|
31
|
+
shortcutJumpSelector = '.t3js-shortcut-jump',
|
|
32
|
+
shortcutDeleteSelector = '.t3js-shortcut-delete',
|
|
33
|
+
shortcutEditSelector = '.t3js-shortcut-edit',
|
|
34
|
+
|
|
35
|
+
shortcutFormSelector = '.t3js-shortcut-form',
|
|
36
|
+
|
|
37
|
+
createShortcutSelector = '[data-dispatch-action="TYPO3.ShortcutMenu.createShortcut"]',
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
interface BookmarkData {
|
|
41
|
+
route: string;
|
|
42
|
+
args: string;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Module: @typo3/backend/toolbar/shortcut-menu
|
|
47
|
+
* shortcut menu logic to add new shortcut, remove a shortcut
|
|
48
|
+
* and edit a shortcut
|
|
49
|
+
*/
|
|
50
|
+
class ShortcutMenu {
|
|
51
|
+
constructor() {
|
|
52
|
+
Viewport.Topbar.Toolbar.registerEvent(this.initializeEvents);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* makes a call to the backend class to create a new shortcut,
|
|
57
|
+
* when finished it reloads the menu
|
|
58
|
+
*
|
|
59
|
+
* @param {String} routeIdentifier
|
|
60
|
+
* @param {String} routeArguments
|
|
61
|
+
* @param {String} displayName
|
|
62
|
+
* @param {String} confirmationText
|
|
63
|
+
* @param {Object} shortcutButton
|
|
64
|
+
*/
|
|
65
|
+
public createShortcut(
|
|
66
|
+
routeIdentifier: string,
|
|
67
|
+
routeArguments: string,
|
|
68
|
+
displayName: string,
|
|
69
|
+
confirmationText: string,
|
|
70
|
+
shortcutButton: HTMLElement,
|
|
71
|
+
): void {
|
|
72
|
+
(new AjaxRequest(TYPO3.settings.ajaxUrls.shortcut_create)).post({
|
|
73
|
+
routeIdentifier: routeIdentifier,
|
|
74
|
+
arguments: routeArguments,
|
|
75
|
+
displayName: displayName,
|
|
76
|
+
}).then(async (response: AjaxResponse): Promise<void> => {
|
|
77
|
+
const jsonResponse = await response.resolve();
|
|
78
|
+
if (jsonResponse.result === 'success') {
|
|
79
|
+
Notification.success(TYPO3.lang['bookmark.savedTitle'], TYPO3.lang['bookmark.savedMessage']);
|
|
80
|
+
} else if (jsonResponse.result === 'alreadyExists') {
|
|
81
|
+
Notification.info(TYPO3.lang['bookmark.alreadyExistsTitle'], TYPO3.lang['bookmark.alreadyExistsMessage']);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Always reload the bookmark menu, could be out-of-sync in the "alreadyExists" case
|
|
85
|
+
this.refreshMenu();
|
|
86
|
+
|
|
87
|
+
if (typeof shortcutButton !== 'object') {
|
|
88
|
+
// @todo: when does this happen?
|
|
89
|
+
console.warn(`Expected argument shortcutButton to be an object, got ${typeof shortcutButton}`);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const isDropdownItem = shortcutButton.classList.contains('dropdown-item');
|
|
94
|
+
const securityUtility = new SecurityUtility();
|
|
95
|
+
Icons.getIcon('actions-system-shortcut-active', Icons.sizes.small).then((icon: string): void => {
|
|
96
|
+
shortcutButton.innerHTML = icon + (isDropdownItem ? ' ' + securityUtility.encodeHtml(TYPO3.lang['labels.alreadyBookmarked']) : '');
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
if (isDropdownItem) {
|
|
100
|
+
shortcutButton.setAttribute('disabled', 'disabled');
|
|
101
|
+
} else {
|
|
102
|
+
shortcutButton.classList.add('active');
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
shortcutButton.dataset.dispatchDisabled = 'disabled';
|
|
106
|
+
shortcutButton.title = securityUtility.encodeHtml(TYPO3.lang['labels.alreadyBookmarked']);
|
|
107
|
+
}).catch((): void => {
|
|
108
|
+
Notification.error(TYPO3.lang['bookmark.failedTitle'], TYPO3.lang['bookmark.failedMessage']);
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
private readonly initializeEvents = (): void => {
|
|
113
|
+
const containerSelector = document.querySelector(Identifiers.containerSelector);
|
|
114
|
+
new RegularEvent('click', (evt: Event, target: HTMLElement): void => {
|
|
115
|
+
evt.preventDefault();
|
|
116
|
+
evt.stopImmediatePropagation();
|
|
117
|
+
|
|
118
|
+
const shortcutItem = target.closest(Identifiers.shortcutItemSelector) as HTMLElement;
|
|
119
|
+
this.deleteShortcut(parseInt(shortcutItem.dataset.shortcutid, 10));
|
|
120
|
+
}).delegateTo(containerSelector, Identifiers.shortcutDeleteSelector);
|
|
121
|
+
|
|
122
|
+
new RegularEvent('click', (evt: Event, target: HTMLElement): void => {
|
|
123
|
+
evt.preventDefault();
|
|
124
|
+
evt.stopImmediatePropagation();
|
|
125
|
+
|
|
126
|
+
const shortcutItem = target.closest(Identifiers.shortcutItemSelector) as HTMLElement;
|
|
127
|
+
this.editShortcut(parseInt(shortcutItem.dataset.shortcutid, 10), shortcutItem.dataset.shortcutgroup);
|
|
128
|
+
}).delegateTo(containerSelector, Identifiers.shortcutEditSelector);
|
|
129
|
+
|
|
130
|
+
new RegularEvent('submit', (evt: Event, target: HTMLFormElement): void => {
|
|
131
|
+
evt.preventDefault();
|
|
132
|
+
evt.stopImmediatePropagation();
|
|
133
|
+
|
|
134
|
+
this.saveShortcutForm(target);
|
|
135
|
+
}).delegateTo(containerSelector, Identifiers.shortcutFormSelector);
|
|
136
|
+
|
|
137
|
+
new RegularEvent('reset', (evt: Event): void => {
|
|
138
|
+
evt.preventDefault();
|
|
139
|
+
evt.stopImmediatePropagation();
|
|
140
|
+
|
|
141
|
+
this.refreshMenu();
|
|
142
|
+
}).delegateTo(containerSelector, Identifiers.shortcutFormSelector);
|
|
143
|
+
|
|
144
|
+
new RegularEvent('click', (evt: Event, target: HTMLAnchorElement): void => {
|
|
145
|
+
evt.preventDefault();
|
|
146
|
+
|
|
147
|
+
const router = document.querySelector('typo3-backend-module-router');
|
|
148
|
+
router.setAttribute('endpoint', target.href);
|
|
149
|
+
router.setAttribute('module', target.dataset.module);
|
|
150
|
+
}).delegateTo(containerSelector, Identifiers.shortcutJumpSelector);
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Removes an existing short by sending an AJAX call
|
|
155
|
+
*
|
|
156
|
+
* @param shortcutId number
|
|
157
|
+
*/
|
|
158
|
+
private deleteShortcut(shortcutId: number): void {
|
|
159
|
+
const modal = Modal.confirm(TYPO3.lang['bookmark.delete'], TYPO3.lang['bookmark.confirmDelete']);
|
|
160
|
+
modal.addEventListener('confirm.button.ok', (): void => {
|
|
161
|
+
(new AjaxRequest(TYPO3.settings.ajaxUrls.shortcut_remove)).post({
|
|
162
|
+
shortcutId,
|
|
163
|
+
}).then(async (response: AjaxResponse): Promise<void> => {
|
|
164
|
+
const data = await response.resolve();
|
|
165
|
+
// a reload is used in order to restore the original behaviour
|
|
166
|
+
// e.g. remove groups that are now empty because the last one in the group
|
|
167
|
+
// was removed
|
|
168
|
+
this.refreshMenu();
|
|
169
|
+
// if we remove bookmark entry for current page, we want to enable the bookmark link
|
|
170
|
+
// again in the dropdown menu
|
|
171
|
+
this.checkIfEnableBookmarkLink(data.data);
|
|
172
|
+
});
|
|
173
|
+
modal.hideModal();
|
|
174
|
+
});
|
|
175
|
+
modal.addEventListener('confirm.button.cancel', (): void => {
|
|
176
|
+
modal.hideModal();
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Build the in-place-editor for a shortcut
|
|
182
|
+
*/
|
|
183
|
+
private editShortcut(shortcutId: number, shortcutGroup: string): void {
|
|
184
|
+
// load the form
|
|
185
|
+
(new AjaxRequest(TYPO3.settings.ajaxUrls.shortcut_editform)).withQueryArguments({
|
|
186
|
+
shortcutId,
|
|
187
|
+
shortcutGroup,
|
|
188
|
+
}).get({ cache: 'no-cache' }).then(async (response: AjaxResponse): Promise<void> => {
|
|
189
|
+
document.querySelector(Identifiers.containerSelector + ' ' + Identifiers.toolbarMenuSelector).innerHTML = await response.resolve();
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Save the data from the in-place-editor for a shortcut
|
|
195
|
+
*/
|
|
196
|
+
private saveShortcutForm(shortcutForm: HTMLFormElement): void {
|
|
197
|
+
(new AjaxRequest(TYPO3.settings.ajaxUrls.shortcut_saveform)).post(new FormData(shortcutForm)).then((): void => {
|
|
198
|
+
Notification.success(TYPO3.lang['bookmark.savedTitle'], TYPO3.lang['bookmark.savedMessage']);
|
|
199
|
+
this.refreshMenu();
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Reloads the menu after an update
|
|
205
|
+
*/
|
|
206
|
+
private refreshMenu(): void {
|
|
207
|
+
const toolbarItemIcon = document.querySelector(Identifiers.containerSelector + ' ' + Identifiers.toolbarIconSelector);
|
|
208
|
+
const existingIcon = toolbarItemIcon.cloneNode(true);
|
|
209
|
+
|
|
210
|
+
const spinner = document.createElement('typo3-backend-spinner');
|
|
211
|
+
spinner.setAttribute('size', Sizes.small);
|
|
212
|
+
toolbarItemIcon.replaceWith(spinner);
|
|
213
|
+
|
|
214
|
+
(new AjaxRequest(TYPO3.settings.ajaxUrls.shortcut_list)).get({ cache: 'no-cache' }).then(async (response: AjaxResponse): Promise<void> => {
|
|
215
|
+
document.querySelector(Identifiers.containerSelector + ' ' + Identifiers.toolbarMenuSelector).innerHTML = await response.resolve();
|
|
216
|
+
}).finally((): void => {
|
|
217
|
+
document.querySelector(Identifiers.containerSelector + ' typo3-backend-spinner').replaceWith(existingIcon);
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
private checkIfEnableBookmarkLink(bookmarkData: BookmarkData): void {
|
|
222
|
+
const shortcutButton: HTMLElement|null = top.list_frame?.document.querySelector(Identifiers.createShortcutSelector);
|
|
223
|
+
if (!shortcutButton) {
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const dispatchArgs = JSON.parse(shortcutButton.dataset.dispatchArgs.replace(/"/g, '"'));
|
|
228
|
+
if (dispatchArgs[0] !== bookmarkData.route || dispatchArgs[1] !== bookmarkData.args) {
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const securityUtility = new SecurityUtility();
|
|
233
|
+
const isDropdownItem = shortcutButton.classList.contains('dropdown-item');
|
|
234
|
+
|
|
235
|
+
Icons.getIcon('actions-system-shortcut-new', Icons.sizes.small).then((icon: string): void => {
|
|
236
|
+
shortcutButton.innerHTML = icon + (isDropdownItem ? ' ' + securityUtility.encodeHtml(TYPO3.lang['labels.makeBookmark']) : '');
|
|
237
|
+
});
|
|
238
|
+
shortcutButton.title = securityUtility.encodeHtml(TYPO3.lang['labels.makeBookmark']);
|
|
239
|
+
delete shortcutButton.dataset.dispatchDisabled;
|
|
240
|
+
|
|
241
|
+
if (isDropdownItem) {
|
|
242
|
+
shortcutButton.removeAttribute('disabled');
|
|
243
|
+
} else {
|
|
244
|
+
shortcutButton.classList.remove('active');
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
if (!top.TYPO3.ShortcutMenu || typeof top.TYPO3.ShortcutMenu !== 'object') {
|
|
250
|
+
top.TYPO3.ShortcutMenu = new ShortcutMenu();
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
const shortcutMenuObject: ShortcutMenu = top.TYPO3.ShortcutMenu;
|
|
254
|
+
export default shortcutMenuObject;
|
|
@@ -0,0 +1,161 @@
|
|
|
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 AjaxRequest from '@typo3/core/ajax/ajax-request';
|
|
15
|
+
import RegularEvent from '@typo3/core/event/regular-event';
|
|
16
|
+
import Icons from '../icons';
|
|
17
|
+
import PersistentStorage from '../storage/persistent';
|
|
18
|
+
import Viewport from '../viewport';
|
|
19
|
+
import { AjaxResponse } from '@typo3/core/ajax/ajax-response';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Explicit selectors to avoid nesting queries
|
|
23
|
+
*/
|
|
24
|
+
enum SystemInformationSelector {
|
|
25
|
+
element = '#typo3-cms-backend-backend-toolbaritems-systeminformationtoolbaritem',
|
|
26
|
+
icon = '#typo3-cms-backend-backend-toolbaritems-systeminformationtoolbaritem .toolbar-item-icon .t3js-icon',
|
|
27
|
+
menu = '#typo3-cms-backend-backend-toolbaritems-systeminformationtoolbaritem .dropdown-menu',
|
|
28
|
+
data = '[data-systeminformation-data]',
|
|
29
|
+
badge = '[data-systeminformation-badge]',
|
|
30
|
+
message = '[data-systeminformation-message-module]',
|
|
31
|
+
messageLink = '[data-systeminformation-message-module] a'
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
interface SystemInformationData {
|
|
35
|
+
count: number,
|
|
36
|
+
severityBadgeClass: string,
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
interface SystemInformationMessageData {
|
|
40
|
+
count: number,
|
|
41
|
+
status: string,
|
|
42
|
+
module: string,
|
|
43
|
+
params: string
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Module: @typo3/backend/toolbar/system-information-menu
|
|
48
|
+
* System information menu handler
|
|
49
|
+
*/
|
|
50
|
+
class SystemInformationMenu {
|
|
51
|
+
private timer: number = null;
|
|
52
|
+
|
|
53
|
+
constructor() {
|
|
54
|
+
new RegularEvent('click', this.handleMessageLinkClick)
|
|
55
|
+
.delegateTo(document, SystemInformationSelector.messageLink);
|
|
56
|
+
Viewport.Topbar.Toolbar.registerEvent(this.updateMenu);
|
|
57
|
+
|
|
58
|
+
// triggred via BackendUtility::setUpdateSignal('updateSystemInformationMenu')
|
|
59
|
+
document.addEventListener('typo3:system-information-menu:update', () => this.updateMenu());
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
private static getData(): SystemInformationData {
|
|
63
|
+
const element: null|HTMLElement = document.querySelector(SystemInformationSelector.data) as HTMLElement;
|
|
64
|
+
const data: null|DOMStringMap = element?.dataset;
|
|
65
|
+
return {
|
|
66
|
+
count: data?.systeminformationDataCount ? parseInt(data.systeminformationDataCount, 10) : 0,
|
|
67
|
+
severityBadgeClass: data?.systeminformationDataSeveritybadgeclass ?? '',
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
private static getMessageDataFromElement(element: HTMLElement): SystemInformationMessageData {
|
|
72
|
+
const data: DOMStringMap = element.dataset;
|
|
73
|
+
return {
|
|
74
|
+
count: data.systeminformationMessageCount ? parseInt(data.systeminformationMessageCount, 10) : 0,
|
|
75
|
+
status: data.systeminformationMessageStatus ?? '',
|
|
76
|
+
module: data.systeminformationMessageModule ?? '',
|
|
77
|
+
params: data.systeminformationMessageParams ?? '',
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
private static updateBadge(): void {
|
|
82
|
+
const data = SystemInformationMenu.getData();
|
|
83
|
+
const element = document.querySelector(SystemInformationSelector.badge) as HTMLElement;
|
|
84
|
+
|
|
85
|
+
// ensure all default classes are available and previous
|
|
86
|
+
// (at this time in processing unknown) class is removed
|
|
87
|
+
element.removeAttribute('class');
|
|
88
|
+
element.classList.add('toolbar-item-badge');
|
|
89
|
+
element.classList.add('badge');
|
|
90
|
+
element.classList.add('badge-pill');
|
|
91
|
+
if (data.severityBadgeClass !== '') {
|
|
92
|
+
element.classList.add(data.severityBadgeClass);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
element.textContent = data.count.toString();
|
|
96
|
+
element.classList.toggle('hidden', !(data.count > 0));
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
private readonly updateMenu = async (): Promise<void> => {
|
|
100
|
+
const toolbarItemIcon = document.querySelector(SystemInformationSelector.icon);
|
|
101
|
+
const currentIcon = toolbarItemIcon.cloneNode(true);
|
|
102
|
+
|
|
103
|
+
if (this.timer !== null) {
|
|
104
|
+
clearTimeout(this.timer);
|
|
105
|
+
this.timer = null;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
Icons.getIcon('spinner-circle', Icons.sizes.small).then((spinner: string): void => {
|
|
109
|
+
toolbarItemIcon.replaceWith(document.createRange().createContextualFragment(spinner));
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
try {
|
|
113
|
+
const response = await new AjaxRequest(TYPO3.settings.ajaxUrls.systeminformation_render).get({ redirect: 'manual' });
|
|
114
|
+
const htmlResult = await response.resolve();
|
|
115
|
+
document.querySelector(SystemInformationSelector.menu).innerHTML = htmlResult;
|
|
116
|
+
SystemInformationMenu.updateBadge();
|
|
117
|
+
} catch (e: unknown) {
|
|
118
|
+
const errorToBeSurpressed = (
|
|
119
|
+
// Backend is not available and returned a redirect to the login page, ignore
|
|
120
|
+
e instanceof AjaxResponse && e.response.type === 'opaqueredirect'
|
|
121
|
+
);
|
|
122
|
+
if (!errorToBeSurpressed) {
|
|
123
|
+
throw e;
|
|
124
|
+
}
|
|
125
|
+
} finally {
|
|
126
|
+
document.querySelector(SystemInformationSelector.icon).replaceWith(currentIcon);
|
|
127
|
+
// reload error data every five minutes
|
|
128
|
+
this.timer = setTimeout(this.updateMenu, 1000 * 300);
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Updates the UC and opens the linked module
|
|
134
|
+
*/
|
|
135
|
+
private handleMessageLinkClick(event: Event, target: HTMLElement): void {
|
|
136
|
+
const messageData = SystemInformationMenu.getMessageDataFromElement(target.closest(SystemInformationSelector.message));
|
|
137
|
+
if (messageData.module === '') {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
event.preventDefault();
|
|
141
|
+
event.stopPropagation();
|
|
142
|
+
|
|
143
|
+
const moduleStorageObject: { [key: string]: object } = {};
|
|
144
|
+
const timestamp = Math.floor(Date.now() / 1000);
|
|
145
|
+
let storedSystemInformationSettings = {};
|
|
146
|
+
if (PersistentStorage.isset('systeminformation')) {
|
|
147
|
+
storedSystemInformationSettings = JSON.parse(PersistentStorage.get('systeminformation'));
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
moduleStorageObject[messageData.module] = { lastAccess: timestamp };
|
|
151
|
+
Object.assign(storedSystemInformationSettings, moduleStorageObject);
|
|
152
|
+
const ajax = PersistentStorage.set('systeminformation', JSON.stringify(storedSystemInformationSettings));
|
|
153
|
+
ajax.then((): void => {
|
|
154
|
+
// finally, open the module now
|
|
155
|
+
TYPO3.ModuleMenu.App.showModule(messageData.module, messageData.params);
|
|
156
|
+
Viewport.Topbar.refresh();
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export default new SystemInformationMenu();
|
|
@@ -0,0 +1,41 @@
|
|
|
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 DocumentService from '@typo3/core/document-service';
|
|
15
|
+
import RegularEvent from '@typo3/core/event/regular-event';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Module: @typo3/backend/toolbar
|
|
19
|
+
* Toolbar component of the TYPO3 backend
|
|
20
|
+
* @exports @typo3/backend/toolbar
|
|
21
|
+
*/
|
|
22
|
+
class Toolbar {
|
|
23
|
+
public static initialize(): void {
|
|
24
|
+
Toolbar.initializeEvents();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
private static initializeEvents(): void {
|
|
28
|
+
new RegularEvent('click', (): void => {
|
|
29
|
+
const scaffold = document.querySelector('.scaffold');
|
|
30
|
+
scaffold.classList.remove('scaffold-modulemenu-expanded');
|
|
31
|
+
scaffold.classList.toggle('scaffold-toolbar-expanded');
|
|
32
|
+
}).bindTo(document.querySelector('.t3js-topbar-button-toolbar'));
|
|
33
|
+
|
|
34
|
+
new RegularEvent('click', (): void => {
|
|
35
|
+
const scaffold = document.querySelector('.scaffold');
|
|
36
|
+
scaffold.classList.remove('scaffold-modulemenu-expanded', 'scaffold-toolbar-expanded');
|
|
37
|
+
}).bindTo(document.querySelector('.t3js-topbar-button-search'));
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
DocumentService.ready().then(Toolbar.initialize);
|
|
@@ -0,0 +1,194 @@
|
|
|
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 { html, LitElement, type TemplateResult } from 'lit';
|
|
15
|
+
import { customElement, query } from 'lit/decorators';
|
|
16
|
+
import AjaxRequest from '@typo3/core/ajax/ajax-request';
|
|
17
|
+
import { type TreeToolbar } from '@typo3/backend/tree/tree-toolbar';
|
|
18
|
+
import ElementBrowser from '@typo3/backend/element-browser';
|
|
19
|
+
import LinkBrowser from '@typo3/backend/link-browser';
|
|
20
|
+
import '@typo3/backend/element/icon-element';
|
|
21
|
+
import { FileStorageTree } from './file-storage-tree';
|
|
22
|
+
import type { AjaxResponse } from '@typo3/core/ajax/ajax-response';
|
|
23
|
+
import type { TreeNodeInterface } from '@typo3/backend/tree/tree-node';
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Extension of the Tree, allowing to show additional actions on the right hand of the tree to directly link
|
|
27
|
+
* select a folder
|
|
28
|
+
*/
|
|
29
|
+
@customElement('typo3-backend-component-filestorage-browser-tree')
|
|
30
|
+
export class FileStorageBrowserTree extends FileStorageTree {
|
|
31
|
+
|
|
32
|
+
protected override createNodeContentAction(node: TreeNodeInterface): TemplateResult {
|
|
33
|
+
if (this.settings.actions.includes('link')) {
|
|
34
|
+
return html`
|
|
35
|
+
<span class="node-action" @click="${() => this.linkItem(node)}">
|
|
36
|
+
<typo3-backend-icon identifier="actions-link" size="small"></typo3-backend-icon>
|
|
37
|
+
</span>
|
|
38
|
+
`;
|
|
39
|
+
} else if (this.settings.actions.includes('select')) {
|
|
40
|
+
return html`
|
|
41
|
+
<span class="node-action" @click="${() => this.selectItem(node)}">
|
|
42
|
+
<typo3-backend-icon identifier="actions-link" size="small"></typo3-backend-icon>
|
|
43
|
+
</span>
|
|
44
|
+
`;
|
|
45
|
+
}
|
|
46
|
+
return super.createNodeContentAction(node);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Link to a folder - Link Handler specific
|
|
51
|
+
*/
|
|
52
|
+
private linkItem(node: TreeNodeInterface): void {
|
|
53
|
+
LinkBrowser.finalizeFunction('t3://folder?storage=' + node.storage + '&identifier=' + node.pathIdentifier);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Element Browser specific
|
|
58
|
+
*/
|
|
59
|
+
private selectItem(node: TreeNodeInterface): void {
|
|
60
|
+
ElementBrowser.insertElement(
|
|
61
|
+
node.recordType,
|
|
62
|
+
node.identifier,
|
|
63
|
+
node.name,
|
|
64
|
+
node.identifier,
|
|
65
|
+
true
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
@customElement('typo3-backend-component-filestorage-browser')
|
|
71
|
+
export class FileStorageBrowser extends LitElement {
|
|
72
|
+
@query('.tree-wrapper') tree: FileStorageBrowserTree;
|
|
73
|
+
|
|
74
|
+
private activeFolder: string = '';
|
|
75
|
+
private actions: Array<string> = [];
|
|
76
|
+
|
|
77
|
+
protected override firstUpdated(): void {
|
|
78
|
+
this.activeFolder = this.getAttribute('active-folder') || '';
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// disable shadow dom for now
|
|
82
|
+
protected override createRenderRoot(): HTMLElement | ShadowRoot {
|
|
83
|
+
return this;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
protected override render(): TemplateResult {
|
|
87
|
+
if (this.hasAttribute('tree-actions') && this.getAttribute('tree-actions').length) {
|
|
88
|
+
this.actions = JSON.parse(this.getAttribute('tree-actions'));
|
|
89
|
+
}
|
|
90
|
+
const treeSetup = {
|
|
91
|
+
dataUrl: top.TYPO3.settings.ajaxUrls.filestorage_tree_data,
|
|
92
|
+
rootlineUrl: top.TYPO3.settings.ajaxUrls.filestorage_tree_rootline,
|
|
93
|
+
filterUrl: top.TYPO3.settings.ajaxUrls.filestorage_tree_filter,
|
|
94
|
+
showIcons: true,
|
|
95
|
+
actions: this.actions
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
const initialized = () => {
|
|
99
|
+
// set up toolbar now with updated properties
|
|
100
|
+
const toolbar = this.querySelector('typo3-backend-tree-toolbar') as TreeToolbar;
|
|
101
|
+
toolbar.tree = this.tree;
|
|
102
|
+
// Expand to the active folder if one is set
|
|
103
|
+
if (this.activeFolder) {
|
|
104
|
+
this.expandToActiveFolder();
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
return html`
|
|
109
|
+
<div class="tree">
|
|
110
|
+
<typo3-backend-tree-toolbar .tree="${this.tree}"></typo3-backend-tree-toolbar>
|
|
111
|
+
<div class="navigation-tree-container">
|
|
112
|
+
<typo3-backend-component-filestorage-browser-tree
|
|
113
|
+
class="tree-wrapper"
|
|
114
|
+
.setup=${treeSetup}
|
|
115
|
+
@tree:initialized=${initialized}
|
|
116
|
+
@typo3:tree:node-selected=${this.loadFolderDetails}
|
|
117
|
+
@typo3:tree:nodes-prepared=${this.selectActiveNode}
|
|
118
|
+
></typo3-backend-component-page-browser-tree>
|
|
119
|
+
</div>
|
|
120
|
+
</div>
|
|
121
|
+
`;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
private readonly selectActiveNode = (evt: CustomEvent): void => {
|
|
125
|
+
// Activate the current node
|
|
126
|
+
const nodes = evt.detail.nodes as Array<TreeNodeInterface>;
|
|
127
|
+
evt.detail.nodes = nodes.map((node: TreeNodeInterface) => {
|
|
128
|
+
if (decodeURIComponent(node.identifier) === this.activeFolder) {
|
|
129
|
+
node.checked = true;
|
|
130
|
+
}
|
|
131
|
+
return node;
|
|
132
|
+
});
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Expand the tree to show the active folder
|
|
137
|
+
*/
|
|
138
|
+
private async expandToActiveFolder(): Promise<void> {
|
|
139
|
+
if (!this.activeFolder || !this.tree.settings.rootlineUrl) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Check if the active node is already in the tree
|
|
144
|
+
const existingNode = this.tree.nodes.find((node) => decodeURIComponent(node.identifier) === this.activeFolder);
|
|
145
|
+
if (existingNode) {
|
|
146
|
+
// Node is already loaded, just expand its parents
|
|
147
|
+
await this.tree.expandNodeParents(existingNode);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Fetch the rootline to find the path to the active folder
|
|
152
|
+
try {
|
|
153
|
+
const url = new URL(this.tree.settings.rootlineUrl, window.location.origin);
|
|
154
|
+
url.searchParams.set('identifier', this.activeFolder);
|
|
155
|
+
const response = await new AjaxRequest(url.toString()).get({ cache: 'no-cache' });
|
|
156
|
+
const { rootline }: { rootline: string[] } = await response.resolve();
|
|
157
|
+
|
|
158
|
+
// Expand all parent nodes
|
|
159
|
+
if (rootline && rootline.length > 0) {
|
|
160
|
+
// Remove the last element (the active folder itself)
|
|
161
|
+
rootline.pop();
|
|
162
|
+
// Encode identifiers to match the URL-encoded format stored in tree nodes
|
|
163
|
+
await this.tree.expandParents(rootline.map(id => encodeURIComponent(id)));
|
|
164
|
+
}
|
|
165
|
+
} catch (error) {
|
|
166
|
+
// If rootline fetch fails, silently ignore (folder might not exist or no access)
|
|
167
|
+
console.debug('Could not expand to active folder:', error);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* If a page is clicked, the content area needs to be updated
|
|
173
|
+
*/
|
|
174
|
+
private readonly loadFolderDetails = (evt: CustomEvent): void => {
|
|
175
|
+
const node = evt.detail.node as TreeNodeInterface;
|
|
176
|
+
if (!node.checked) {
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
const contentsUrl = document.location.href + '&contentOnly=1&expandFolder=' + node.identifier;
|
|
180
|
+
(new AjaxRequest(contentsUrl)).get()
|
|
181
|
+
.then((response: AjaxResponse) => response.resolve())
|
|
182
|
+
.then((response) => {
|
|
183
|
+
const contentContainer = document.querySelector('.element-browser-main-content .element-browser-body') as HTMLElement;
|
|
184
|
+
contentContainer.innerHTML = response;
|
|
185
|
+
});
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
declare global {
|
|
190
|
+
interface HTMLElementTagNameMap {
|
|
191
|
+
'typo3-backend-component-filestorage-browser-tree': FileStorageBrowserTree;
|
|
192
|
+
'typo3-backend-component-filestorage-browser': FileStorageBrowser;
|
|
193
|
+
}
|
|
194
|
+
}
|