[FEATURE] Re-Design the AdminPanel 84/57084/38
authorSusanne Moog <susanne.moog@typo3.org>
Tue, 29 May 2018 21:52:24 +0000 (23:52 +0200)
committerBenni Mack <benni@typo3.org>
Fri, 27 Jul 2018 21:37:30 +0000 (23:37 +0200)
Major refactoring of the admin panel:

- Split content in modules and sub-modules
- Modules are indepent and pluggable
- Modernized design
- Better extensibility
- Clearer separation of page and module settings

For more information see .rst files.

Resolves: #84584
Releases: master
Change-Id: Iad4dfbc485e1c1280bbdb2e7fb0dcdc9f90bf537
Reviewed-on: https://review.typo3.org/57084
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Andreas Fernandez <a.fernandez@scripting-base.de>
Tested-by: Andreas Fernandez <a.fernandez@scripting-base.de>
Reviewed-by: Georg Ringer <georg.ringer@gmail.com>
Tested-by: Georg Ringer <georg.ringer@gmail.com>
Reviewed-by: Benni Mack <benni@typo3.org>
Tested-by: Benni Mack <benni@typo3.org>
89 files changed:
Build/Resources/Public/Sass/adminpanel.scss
typo3/sysext/adminpanel/Classes/Controller/AjaxController.php
typo3/sysext/adminpanel/Classes/Controller/MainController.php
typo3/sysext/adminpanel/Classes/Hooks/RenderHook.php
typo3/sysext/adminpanel/Classes/Middleware/AdminPanelInitiator.php
typo3/sysext/adminpanel/Classes/Modules/AbstractModule.php
typo3/sysext/adminpanel/Classes/Modules/AbstractSubModule.php [new file with mode: 0644]
typo3/sysext/adminpanel/Classes/Modules/AdminPanelModuleInterface.php
typo3/sysext/adminpanel/Classes/Modules/AdminPanelSubModuleInterface.php [new file with mode: 0644]
typo3/sysext/adminpanel/Classes/Modules/CacheModule.php
typo3/sysext/adminpanel/Classes/Modules/EditModule.php
typo3/sysext/adminpanel/Classes/Modules/Info/GeneralInformation.php [new file with mode: 0644]
typo3/sysext/adminpanel/Classes/Modules/Info/PhpInformation.php [new file with mode: 0644]
typo3/sysext/adminpanel/Classes/Modules/Info/RequestInformation.php [new file with mode: 0644]
typo3/sysext/adminpanel/Classes/Modules/InfoModule.php
typo3/sysext/adminpanel/Classes/Modules/PreviewModule.php
typo3/sysext/adminpanel/Classes/Modules/TsDebug/TypoScriptWaterfall.php [new file with mode: 0644]
typo3/sysext/adminpanel/Classes/Modules/TsDebugModule.php
typo3/sysext/adminpanel/Classes/Service/ConfigurationService.php [new file with mode: 0644]
typo3/sysext/adminpanel/Classes/Service/ModuleLoader.php
typo3/sysext/adminpanel/Classes/View/AdminPanelView.php
typo3/sysext/adminpanel/Resources/Private/Language/locallang.xlf [new file with mode: 0644]
typo3/sysext/adminpanel/Resources/Private/Language/locallang_cache.xlf
typo3/sysext/adminpanel/Resources/Private/Language/locallang_edit.xlf
typo3/sysext/adminpanel/Resources/Private/Language/locallang_info.xlf
typo3/sysext/adminpanel/Resources/Private/Language/locallang_tsdebug.xlf
typo3/sysext/adminpanel/Resources/Private/Layouts/Default.html [new file with mode: 0644]
typo3/sysext/adminpanel/Resources/Private/Partials/Data/TableKeyValue.html [new file with mode: 0644]
typo3/sysext/adminpanel/Resources/Private/Partials/Form/Checkbox.html [new file with mode: 0644]
typo3/sysext/adminpanel/Resources/Private/Partials/Form/DateTime.html [new file with mode: 0644]
typo3/sysext/adminpanel/Resources/Private/Partials/Form/Hidden.html [new file with mode: 0644]
typo3/sysext/adminpanel/Resources/Private/Partials/Form/Select.html [new file with mode: 0644]
typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Cache/ClearCacheButton.html [deleted file]
typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Cache/ClearLevels.html [deleted file]
typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Cache/NoCache.html [deleted file]
typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Cache/UpdateButton.html [deleted file]
typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Edit/BackendButton.html [deleted file]
typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Edit/FeEdit.html [deleted file]
typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Edit/Toolbar.html [deleted file]
typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Info/DocumentSize.html [deleted file]
typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Info/FeUserGroupList.html [deleted file]
typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Info/FrontendUser.html [deleted file]
typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Info/ImagesOnPage.html [deleted file]
typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Info/Page.html [deleted file]
typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Info/PageCache.html [deleted file]
typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Info/TotalParsetime.html [deleted file]
typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Info/UserIntObjects.html [deleted file]
typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Item.html [new file with mode: 0644]
typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Preview/FluidDebug.html [deleted file]
typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Preview/FrontendUserGroup.html [deleted file]
typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Preview/HiddenPages.html [deleted file]
typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Preview/HiddenRecords.html [deleted file]
typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Preview/ShowHiddenElements.html [deleted file]
typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Preview/SimulateDate.html [deleted file]
typo3/sysext/adminpanel/Resources/Private/Partials/Modules/TsDebug/DisplayContent.html [deleted file]
typo3/sysext/adminpanel/Resources/Private/Partials/Modules/TsDebug/DisplayMessages.html [deleted file]
typo3/sysext/adminpanel/Resources/Private/Partials/Modules/TsDebug/DisplayTimes.html [deleted file]
typo3/sysext/adminpanel/Resources/Private/Partials/Modules/TsDebug/ForceTemplateParsing.html [deleted file]
typo3/sysext/adminpanel/Resources/Private/Partials/Modules/TsDebug/TrackContentRendering.html [deleted file]
typo3/sysext/adminpanel/Resources/Private/Partials/Modules/TsDebug/Tree.html [deleted file]
typo3/sysext/adminpanel/Resources/Private/Partials/Modules/TsDebug/TypoScriptLog.html [deleted file]
typo3/sysext/adminpanel/Resources/Private/Templates/Main.html [new file with mode: 0644]
typo3/sysext/adminpanel/Resources/Private/Templates/Modules/Cache.html [deleted file]
typo3/sysext/adminpanel/Resources/Private/Templates/Modules/Edit.html [deleted file]
typo3/sysext/adminpanel/Resources/Private/Templates/Modules/Info.html [deleted file]
typo3/sysext/adminpanel/Resources/Private/Templates/Modules/Info/General.html [new file with mode: 0644]
typo3/sysext/adminpanel/Resources/Private/Templates/Modules/Info/PhpInfo.html [new file with mode: 0644]
typo3/sysext/adminpanel/Resources/Private/Templates/Modules/Info/RequestInformation.html [new file with mode: 0644]
typo3/sysext/adminpanel/Resources/Private/Templates/Modules/Preview.html [deleted file]
typo3/sysext/adminpanel/Resources/Private/Templates/Modules/Settings/Cache.html [new file with mode: 0644]
typo3/sysext/adminpanel/Resources/Private/Templates/Modules/Settings/Edit.html [new file with mode: 0644]
typo3/sysext/adminpanel/Resources/Private/Templates/Modules/Settings/Preview.html [new file with mode: 0644]
typo3/sysext/adminpanel/Resources/Private/Templates/Modules/TsDebug.html [deleted file]
typo3/sysext/adminpanel/Resources/Private/Templates/Modules/TsDebug/TypoScript.html [new file with mode: 0644]
typo3/sysext/adminpanel/Resources/Private/Templates/Modules/TsDebug/TypoScriptSettings.html [new file with mode: 0644]
typo3/sysext/adminpanel/Resources/Public/Css/adminpanel.css
typo3/sysext/adminpanel/Resources/Public/JavaScript/AdminPanel.js
typo3/sysext/adminpanel/Resources/Public/JavaScript/Modules/Cache.js [new file with mode: 0644]
typo3/sysext/adminpanel/Resources/Public/JavaScript/Modules/Edit.js [new file with mode: 0644]
typo3/sysext/adminpanel/Resources/Public/JavaScript/Modules/Edit/OpenBackendHandler.js [deleted file]
typo3/sysext/adminpanel/Resources/Public/JavaScript/Modules/Preview.js [new file with mode: 0644]
typo3/sysext/adminpanel/Resources/Public/JavaScript/Modules/TsDebug.js [new file with mode: 0644]
typo3/sysext/adminpanel/Tests/Unit/Middleware/AdminPanelInitiatorTest.php
typo3/sysext/adminpanel/Tests/Unit/Modules/PreviewModuleTest.php [new file with mode: 0644]
typo3/sysext/adminpanel/ext_localconf.php
typo3/sysext/core/Classes/TimeTracker/TimeTracker.php
typo3/sysext/core/Documentation/Changelog/master/Deprecation-84584-AdminPanelViewIsAdminModuleEnabledAndExt_makeToolbarDeprecated.rst [new file with mode: 0644]
typo3/sysext/core/Documentation/Changelog/master/Feature-84584-Re-DesignTheAdminPanel.rst [new file with mode: 0644]
typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallMatcher.php

index 7e63895..0974c9d 100644 (file)
 //
 // Load Variables
 //
-@import "variables/main";
 @import "bootstrap/variables";
+@import "variables/main";
 
 //
-// Shared Components
+// Variables
 //
-#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel,
-.typo3-editPanel-btn,
-.typo3-editPanel-link {
-    @import "component/icon";
-}
+$adminPanel-zindex: 99990;
+$adminPanel-zindex-backdrop: 99991;
+$adminPanel-zindex-bar: 99992;
+$adminPanel-prefix: '#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel';
+$adminPanel-bg: $gray-darker;
+$adminPanel-color: $gray-lighter;
+$adminPanel-success: #629755;
+$adminPanel-danger: $brand-danger;
+
+// Bar
+$adminPanel-bar-height: 36px;
+$adminPanel-bar-bg: #424242;
+$adminPanel-bar-border-color: #383838;
+$adminPanel-bar-color: #fff;
+$adminPanel-bar-active-bg: #525252;
+$adminPanel-bar-hover-bg: #525252;
+
+// Header
+$adminPanel-header-height: 36px;
+$adminPanel-header-bg: #eaeaea;
+$adminPanel-header-border-color: #dadada;
+$adminPanel-header-color: #333;
+$adminPanel-header-active-bg: #fafafa;
+$adminPanel-header-hover-bg: #e1e1e1;
+
+// Content
+$adminPanel-content-padding: 20px;
+$adminPanel-content-bg: #fafafa;
+$adminPanel-content-border-color: #dadada;
+$adminPanel-content-color: #333;
+
+// Table
+$adminPanel-table-bg: #fff;
+$adminPanel-table-border: #e0e0e0;
+$adminPanel-table-header-bg: #e0e0e0;
+
+// Card
+$adminPanel-card-bg: #fff;
+$adminPanel-card-padding: 20px;
 
-/*!
- *  Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome
- *  License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
- */
+// Input
+$adminPanel-input-bg: #fff;
+$adminPanel-input-border: #dadada;
+$adminPanel-input-hover-border: #cacaca;
+$adminPanel-input-border-radius: 2px;
+$adminPanel-input-vertical-padding: 1.25em;
+$adminPanel-input-horizontal-padding: 0.75em;
 
-/* FONT PATH
- * -------------------------- */
+//
+// Mixins
+//
+@mixin make-col($size, $columns: 12) {
+    flex: 0 0 percentage($size / $columns);
+    max-width: percentage($size / $columns);
+}
+
+//
+// Font Awesome
+//
 @font-face {
     font-family: 'TYPO3FontAwesome';
-    src: url('../../../../backend/Resources/Public/Fonts/FontAwesome/fontawesome-webfont.eot?v=4.6.3');
-    src: url('../../../../backend/Resources/Public/Fonts/FontAwesome/fontawesome-webfont.eot?#iefix&v=4.6.3') format('embedded-opentype'), url('../../../../backend/Resources/Public/Fonts/FontAwesome/fontawesome-webfont.woff2?v=4.6.3') format('woff2'), url('../../../../backend/Resources/Public/Fonts/FontAwesome/fontawesome-webfont.woff?v=4.6.3') format('woff'), url('../../../../backend/Resources/Public/Fonts/FontAwesome/fontawesome-webfont.ttf?v=4.6.3') format('truetype'), url('../../../../backend/Resources/Public/Fonts/FontAwesome/fontawesome-webfont.svg?v=4.6.3#fontawesomeregular') format('svg');
+    src: url('#{$fa-font-path}/fontawesome-webfont.eot?v=4.6.3');
+    src: url('#{$fa-font-path}/fontawesome-webfont.eot?#iefix&v=4.6.3') format('embedded-opentype'), url('#{$fa-font-path}/fontawesome-webfont.woff2?v=4.6.3') format('woff2'), url('#{$fa-font-path}/fontawesome-webfont.woff?v=4.6.3') format('woff'), url('#{$fa-font-path}/fontawesome-webfont.ttf?v=4.6.3') format('truetype'), url('#{$fa-font-path}/fontawesome-webfont.svg?v=4.6.3#fontawesomeregular') format('svg');
     font-weight: normal;
     font-style: normal;
 }
 
-/*!
- * Font Awesome icons are prefixed with #TSFE_ADMIN_PANEL_FORM to prevent issues with
- * CSS from the website that uses Font Awesome too.
- */
-#TSFE_ADMIN_PANEL_FORM,
-.typo3-feedit-element,
-.typo3-editPanel {
-    .fa:before {
-        display: inline-block;
-        font: normal normal normal 14px/1 TYPO3FontAwesome;
-        font-size: 15px;
-        text-rendering: auto;
-        -webkit-font-smoothing: antialiased;
-        -moz-osx-font-smoothing: grayscale;
-        transform: translate(0, 0);
-    }
-
-    .fa-pencil:before {
-        content: "\f040";
-    }
-
-    .fa-angle-up:before {
-        content: "\f106";
-    }
-
-    .fa-angle-down:before {
-        content: "\f107";
-    }
+//
+// Reset
+//
+#{$adminPanel-prefix} {
+    z-index: $adminPanel-zindex;
 
-    .fa-toggle-off:before {
-        content: "\f204";
+    * {
+        background: none;
+        border: 0;
+        box-shadow: none;
+        box-sizing: border-box;
+        vertical-align: baseline;
+        letter-spacing: normal;
+        width: auto;
+        height: auto;
+        font-family: $font-family-sans-serif;
+        font-size: $font-size-base;
+        font-weight: normal;
+        white-space: normal;
+        margin: 0;
+        padding: 0;
     }
 
-    .fa-toggle-on:before {
-        content: "\f205";
+    *,
+    *:active,
+    *:focus,
+    *:hover {
+        outline: 0;
     }
+}
 
-    .fa-google-plus-square:before {
-        content: "\f0d4";
-    }
+//
+// Shared Components
+//
+#{$adminPanel-prefix} {
+    @import "component/icon";
+}
 
-    .fa-trash:before {
-        content: "\f1f8";
+//
+// Backdrop
+//
+#{$adminPanel-prefix} {
+    .typo3-adminPanel-backdrop {
+        z-index: $adminPanel-zindex-backdrop;
+        content: '';
+        position: fixed;
+        top: 0;
+        left: 0;
+        right: 0;
+        bottom: 0;
+        background-color: rgba(0, 0, 0, 0.5);
     }
+}
 
-    .fa-history:before {
-        content: "\f1da";
+//
+// Bar
+//
+#{$adminPanel-prefix} {
+    .typo3-adminPanel-bar {
+        z-index: $adminPanel-zindex-bar;
+        display: flex;
+        flex-flow: row;
+        justify-content: stretch;
+        position: fixed;
+        bottom: 0;
+        left: auto;
+        right: 0;
+        height: $adminPanel-bar-height + 1px;
+        background-color: $adminPanel-bar-bg;
+        color: $adminPanel-bar-color;
+        border-bottom: 1px solid $adminPanel-bar-border-color;
     }
 
-    .fa-list-alt:before {
-        content: "\f022";
+    &.typo3-adminPanel-active .typo3-adminPanel-bar {
+        left: 0;
     }
 
-    .fa-plus-square:before {
-        content: "\f0fe";
-    }
+    @media (min-width: 768px) {
+        .typo3-adminPanel-bar {
+            right: 20px;
+        }
 
-    .fa-arrows:before {
-        content: "\f047";
+        &.typo3-adminPanel-active .typo3-adminPanel-bar {
+            left: 20px;
+        }
     }
+}
 
-    .fa-exclamation-circle:before {
-        content: "\f06a";
+//
+// Module
+//
+#{$adminPanel-prefix} {
+    .typo3-adminPanel-module {
+        display: flex;
+        padding: 0 10px;
+        align-items: center;
+        border-right: 1px solid $adminPanel-bar-border-color;
     }
 
-    .fa-exclamation-triangle:before {
-        content: "\f071";
+    .typo3-adminPanel-module-settings {
+        margin-left: auto;
     }
 
-    .fa-info-circle:before {
-        content: "\f05a";
+    .typo3-adminPanel-module-logo + .typo3-adminPanel-module-toggle {
+        border-left: none;
     }
 
-    .fa-caret-down:before {
-        content: "\f0d7";
-    }
+    .typo3-adminPanel-module-settings {
+        .typo3-adminPanel-module-trigger-label {
+            display: none;
 
-    .fa-caret-up:before {
-        content: "\f0d8";
+            @media (min-width: $screen-sm) {
+                display: block;
+            }
+        }
     }
 
-    .fa-bolt:before {
-        content: "\f0e7";
+    .typo3-adminPanel-module-settings,
+    .typo3-adminPanel-module-toggle {
+        border-left: 1px solid $adminPanel-bar-border-color;
+        border-right: none;
     }
 }
 
 //
-// Placeholder
+// Module Group
 //
-%adminpanelicon {
-    &:before {
-        display: inline-block;
-        font: normal normal normal 14px/1 TYPO3FontAwesome;
-        font-size: 15px;
-        text-rendering: auto;
-        -webkit-font-smoothing: antialiased;
-        -moz-osx-font-smoothing: grayscale;
-        transform: translate(0, 0);
-    }
-}
-
-%basestyles {
-    background-color: #fafafa;
-    color: #333;
-    font-family: sans-serif;
-    font-size: 12px;
-    line-height: 1.35em;
-
-    a {
-        color: inherit;
-        text-decoration: none;
+#{$adminPanel-prefix} {
+    .typo3-adminPanel-module-group {
+        width: 100%;
+        overflow: hidden;
+        display: flex;
     }
 }
 
 //
-// Container
+// Trigger
 //
-#TSFE_ADMIN_PANEL_FORM {
-    display: block !important;
-    position: fixed;
-    bottom: 0;
-    left: 0;
-    max-width: 100%;
-    max-height: 100%;
-    z-index: 10002;
-    padding: 0;
-    margin: 0;
+#{$adminPanel-prefix} {
+    .typo3-adminPanel-module-trigger {
+        display: flex;
+        align-items: center;
+        padding: 0 10px;
+        margin-left: -10px;
+        margin-right: -10px;
+        font-size: 12px;
+        color: #fff;
+        height: $adminPanel-bar-height;
 
-    * {
-        box-sizing: border-box;
+        > span {
+            white-space: nowrap;
+
+            + span {
+                margin-left: 4px;
+            }
+        }
     }
 
-    *,
-    *:focus,
-    *:hover,
-    *:active {
-        outline: none;
+    .typo3-adminPanel-module-active .typo3-adminPanel-module-trigger {
+        background-color: $adminPanel-bar-active-bg;
     }
 
-    *:before,
-    *:after {
-        -webkit-box-sizing: border-box;
-        -moz-box-sizing: border-box;
-        box-sizing: border-box;
+    [data-typo3-role="typo3-adminPanel-module-trigger"],
+    [data-typo3-role="typo3-adminPanel-trigger"] {
+        cursor: pointer;
+
+        &:focus,
+        &:hover {
+            background-color: $adminPanel-bar-hover-bg;
+        }
     }
-}
 
-//
-// Panel
-//
-#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel {
-    @extend %basestyles;
+    .typo3-adminPanel-module-trigger-icon {
+        .icon-color {
+            fill: currentColor;
+        }
 
-    border: 1px solid #cacaca;
-    max-height: 100vh;
-    max-width: 100%;
-    min-width: 280px;
-    border-left: 0;
-    border-bottom: 0;
-    border-top-left-radius: 2px;
-    display: flex;
-    flex-direction: column;
+        .icon-actions-edit-hide {
+            color: $adminPanel-success;
+        }
+
+        .icon-actions-edit-unhide {
+            color: $adminPanel-danger;
+        }
+    }
+
+    .typo3-adminPanel-module-trigger-information {
+        display: none;
+        opacity: 0.5;
+
+        @media (min-width: $screen-sm) {
+            display: block;
+        }
+    }
 }
 
 //
-// Enabling
+// Content
 //
-#TSFE_ADMIN_PANEL_FORM {
-    #typo3AdminPanelCollapse {
+#{$adminPanel-prefix} {
+    .typo3-adminPanel-content {
         display: none;
-    }
-
-    #typo3AdminPanelEnable:checked + #typo3AdminPanelCollapse + .typo3-adminPanel {
-        .typo3-adminPanel-header {
-            .typo3-adminPanel-header-enable-enabled {
-                display: inline;
-            }
+        flex-direction: column;
+        position: fixed;
+        bottom: $adminPanel-bar-height + 1;
+        top: 20vh;
+        left: 20px;
+        right: 20px;
+        background-color: $adminPanel-content-bg;
+        color: $adminPanel-content-color;
+        border-bottom: 1px solid $adminPanel-bar-border-color;
+    }
+
+    .typo3-adminPanel-content-main {
+        position: relative;
+        padding: 20px;
+        height: 100%;
+        overflow: auto;
 
-            .typo3-adminPanel-header-collapse {
-                display: block;
-            }
+        > *:first-child {
+            margin-top: 0;
         }
-    }
 
-    #typo3AdminPanelCollapse:checked + .typo3-adminPanel {
-        .typo3-adminPanel-actions,
-        .typo3-adminPanel-body {
-            display: none;
+        > *:last-child {
+            margin-bottom: 0;
         }
+    }
 
-        .typo3-adminPanel-header {
-            .typo3-adminPanel-header-collapse-enabled {
-                display: inline;
-            }
+    .typo3-adminPanel-module-active {
+        .typo3-adminPanel-content {
+            display: flex;
         }
     }
 }
 
 //
-// Header
+// Content Header
 //
-#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel {
-    .typo3-adminPanel-header {
+#{$adminPanel-prefix} {
+    .typo3-adminPanel-content-header {
         position: relative;
-        background-color: $brand-notice;
-        color: #fafafa;
-        padding: 1em 3em;
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        height: $adminPanel-header-height + 1;
+        flex-shrink: 0;
+        color: $adminPanel-header-color;
+        background-color: $adminPanel-header-bg;
 
-        .typo3-adminPanel-header-user:before {
-            content: ':';
-            margin-right: 0.5em;
-        }
-
-        .typo3-adminPanel-header-enable,
-        .typo3-adminPanel-header-collapse {
+        &:before {
+            content: '';
             position: absolute;
-            cursor: pointer;
-            top: 50%;
+            bottom: 0;
             left: 0;
-            padding: 1em;
-            transform: translate(0, -50%);
+            right: 0;
+            height: 1px;
+            background-color: $adminPanel-header-border-color;
         }
+    }
 
-        .typo3-adminPanel-header-collapse {
-            display: none;
-            left: auto;
-            right: 0;
+    .typo3-adminPanel-content-header-item {
+        display: flex;
+        align-items: center;
+        height: $adminPanel-header-height + 1;
+        padding: 0 10px;
+        border-right: 1px solid $adminPanel-header-border-color;
+        border-bottom: 1px solid $adminPanel-header-border-color;
+    }
+
+    a.typo3-adminPanel-content-header-item {
+        color: inherit;
+        text-decoration: none;
+        position: relative;
+
+        &:hover,
+        &:focus {
+            background-color: $adminPanel-header-hover-bg;
         }
 
-        .typo3-adminPanel-header-enable-enabled {
-            color: $brand-success;
+        &.typo3-adminPanel-content-header-item-active {
+            background-color: $adminPanel-header-active-bg;
+
+            &:before {
+                content: '';
+                position: absolute;
+                bottom: -1px;
+                left: 0;
+                right: 0;
+                height: 1px;
+                background-color: $adminPanel-header-active-bg;
+            }
         }
+    }
+
+    .typo3-adminPanel-content-header-title {
+        position: relative;
+        color: $adminPanel-bar-color;
+        background-color: $adminPanel-bar-bg;
+        border-right: 1px solid $adminPanel-bar-border-color;
 
-        .typo3-adminPanel-header-enable-disabled {
-            color: $brand-danger;
+        &:before {
+            content: '';
+            position: absolute;
+            bottom: -1px;
+            left: 0;
+            right: 0;
+            height: 1px;
+            background-color: lighten($adminPanel-bar-border-color, 15%);
         }
 
-        .typo3-adminPanel-header-collapse-enabled {
-            display: none;
+        > span + span {
+            margin-left: 4px;
         }
     }
+
+    .typo3-adminPanel-content-header-settings,
+    .typo3-adminPanel-content-header-close {
+        cursor: pointer;
+        border-right: 0;
+        border-left: 1px solid $adminPanel-header-border-color;
+    }
 }
 
 //
-// Actions
+// Content Navigation
 //
-#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel {
-    .typo3-adminPanel-actions {
-        text-align: right;
-        padding: 0 1em 0.75em;
-        background-color: $brand-notice;
-        color: #fafafa;
+#{$adminPanel-prefix} {
+    .typo3-adminPanel-content-nav {
+        width: 100%;
+        overflow: hidden;
+        display: flex;
     }
 }
 
 //
-// Body
+// Content Settings
 //
-#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel {
-    .typo3-adminPanel-body {
-        height: 100%;
-        overflow: auto;
+#{$adminPanel-prefix} {
+    .typo3-adminPanel-content-settings {
+        flex-shrink: 0;
+        max-height: 50%;
+        overflow-y: auto;
+        display: none;
+        background-color: $adminPanel-content-bg;
+        padding: $adminPanel-content-padding;
+        border-bottom: 1px solid $adminPanel-content-border-color;
+        box-shadow: 0 0 1px rgba(0, 0, 0, 0.1);
 
-        > .typo3-adminPanel-section-title:first-child {
-            border-top: none;
+        &.typo3-adminPanel-content-settings-active {
+            display: block;
         }
     }
-}
-
-//
-// Section
-//
-#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel {
-    .typo3-adminPanel-section-title {
-        position: relative;
-        overflow: hidden;
-        border-top: 1px solid #bbb;
-        background-color: #eee;
-        padding: 0.75em 3em 0.75em 1em;
 
-        &:hover {
-            background-color: #ddd;
+    .typo3-adminPanel-content-settings,
+    .typo3-adminPanel-content-settings-group {
+        > *:first-child {
+            margin-top: 0;
         }
 
-        a {
-            position: relative;
-            display: block;
-            padding: 0.75em 3em 0.75em 1em;
-            margin: -0.75em -3em -0.75em -1em;
+        > *:last-child {
+            margin-bottom: 0;
         }
     }
 
-    .typo3-adminPanel-section-title-identifier {
+    .typo3-adminPanel-content-settings-group + .typo3-adminPanel-content-settings-group {
+        margin-top: $adminPanel-content-padding;
+        padding-top: $adminPanel-content-padding;
+        border-top: 1px solid rgba(0, 0, 0, 0.1);
+    }
+}
+
+//
+// Tabs
+//
+#{$adminPanel-prefix} {
+    .typo3-adminPanel-content-panes {
         position: absolute;
-        top: 50%;
+        top: 0;
+        bottom: 0;
+        left: 0;
         right: 0;
-        padding: 1em;
-        transform: translate(0, -50%);
+        display: flex;
+    }
 
-        @extend %adminpanelicon;
+    .typo3-adminPanel-content-panes-item {
+        display: none;
+        overflow: auto;
+        height: 100%;
+        width: 100%;
+        padding: $adminPanel-content-padding;
 
-        &:before {
-            content: "\f105";
+        > *:first-child {
+            margin-top: 0;
         }
-    }
 
-    .typo3-adminPanel-section-open {
-        .typo3-adminPanel-section-title-identifier:before {
-            content: "\f107 ";
+        > *:last-child {
+            margin-bottom: 0;
         }
     }
 
-    .typo3-adminPanel-section-body {
-        padding: 0.75em 1em;
+    .typo3-adminPanel-content-panes-item-active {
+        display: block;
     }
 }
 
 //
-// Inputs
+// Row
 //
-#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel {
-    label {
-        display: block;
-        font-weight: normal;
-        padding: 0;
-        margin: 0;
-        overflow: hidden;
+#{$adminPanel-prefix} {
+    .typo3-adminPanel-row {
+        display: flex;
+        flex-wrap: wrap;
+        padding: 0.25em 0;
+        margin-left: -0.75em;
+        margin-right: -0.75em;
     }
 
-    input[type=text],
-    select {
-        display: block;
-        width: 100%;
-        padding: 0.5em;
-        border: 1px solid #ccc;
-        margin: 0.5em 0;
-        font-size: inherit;
-
-        &:focus,
-        &:hover {
-            border-color: #aaa;
+    .typo3-adminPanel-row-header {
+        > * {
+            font-weight: bold;
         }
     }
 
-    .typo3-adminPanel-form-group {
-        margin: 1em 0;
+    .typo3-adminPanel-col {
+        padding: 0.25em 0.75em;
+        word-break: break-all;
     }
 
-    .typo3-adminPanel-form-group-checkbox,
-    .typo3-adminPanel-form-group-radio {
-        margin: 0.5em 0;
-
-        label {
-            padding-left: 20px;
+    @for $i from 1 through 12 {
+        .typo3-adminPanel-col-#{$i} {
+            @include make-col($i);
         }
+    }
 
-        input[type=checkbox],
-        input[type=radio] {
-            float: left;
-            padding: 0;
-            margin: 1px 0 0 -20px;
+    @media (max-width: $screen-sm-max) {
+        @for $i from 1 through 12 {
+            .typo3-adminPanel-col-sm-#{$i} {
+                @include make-col($i);
+            }
         }
     }
 }
 
 //
+// Text
+//
+#{$adminPanel-prefix} {
+    .typo3-adminPanel-headline {
+        font-weight: bold;
+        margin-top: 1.5em;
+        margin-bottom: 0.75em;
+    }
+
+    h1.typo3-adminPanel-headline {
+        font-weight: normal;
+        font-size: 1.75em;
+    }
+
+    h2.typo3-adminPanel-headline {
+        font-weight: normal;
+        font-size: 1.5em;
+    }
+
+    h3.typo3-adminPanel-headline {
+        font-size: 1.35em;
+    }
+
+    h4.typo3-adminPanel-headline {
+        font-size: 1.25em;
+    }
+}
+
+//
 // Table
 //
-#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel {
+#{$adminPanel-prefix} {
     .typo3-adminPanel-table-overflow {
-        max-width: 100%;
-        margin: 1em 0;
+        display: block;
+        width: 100%;
         overflow-x: auto;
+        -webkit-overflow-scrolling: touch;
+        -ms-overflow-style: -ms-autohiding-scrollbar;
+        border: 1px solid $adminPanel-table-border;
+        box-shadow: 0 0 1px rgba(0, 0, 0, 0.15);
+
+        .typo3-adminPanel-table {
+            border: none;
+        }
     }
 
     .typo3-adminPanel-table {
         width: 100%;
-        border: 1px solid #ccc;
-        border-collapse: collapse;
+        max-width: 100%;
+        background-color: $adminPanel-table-bg;
+        display: table;
+        border-collapse: separate;
         border-spacing: 0;
-
-        td,
-        th {
-            text-align: left;
-            overflow: hidden;
-            position: relative;
-            vertical-align: top;
-            padding: 0.75em;
-        }
+        border: 1px solid $adminPanel-table-border;
 
         thead {
             tr {
-                background-color: rgba(0, 0, 0, 0.15);
+                background-color: $adminPanel-table-header-bg;
             }
 
-            td,
-            th {
-                font-weight: normal;
+            th,
+            td {
+                border-top: none;
             }
         }
 
-        tbody {
-            tr:nth-of-type(odd) {
-                background-color: rgba(0, 0, 0, 0.05);
+        th {
+            font-weight: bold;
+            text-align: inherit;
+
+            > span {
+                font-weight: bold;
             }
         }
-    }
 
-    .typo3-adminPanel-table-cell-content {
-        word-wrap: break-word;
+        tr {
+            font-family: inherit;
+        }
+
+        th,
+        td {
+            padding: 0.75em;
+            vertical-align: top;
+            border-top: 1px solid #dee2e6;
+        }
     }
 
-    .typo3-adminPanel-table-cell-nowrap {
-        white-space: nowrap;
+    .typo3-adminPanel-table-debug {
+        tbody {
+            font-family: monospace;
+
+            * {
+                font-family: inherit;
+            }
+
+            td {
+                word-wrap: break-word;
+            }
+        }
     }
 
-    .typo3-adminPanel-logRow-highlight {
-        background-color: #fcd3cf;
+    .typo3-adminPanel-table-cell-key {
+        width: 19%;
     }
 
-    .stackPointer {
-        color: maroon;
-        vertical-align: top;
+    .typo3-adminPanel-table-cell-nowrap {
+        white-space: nowrap;
     }
 }
 
 //
-// Button
+// Cards
 //
-#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel {
-    .typo3-adminPanel-btn {
-        display: inline-block;
-        margin-bottom: 0;
-        padding: 6px 8px;
-        border: 1px solid transparent;
-        border-radius: 0;
-        font-weight: normal;
-        line-height: 1.5;
-        text-align: center;
-        vertical-align: middle;
-        touch-action: manipulation;
-        cursor: pointer;
-        white-space: nowrap;
-        user-select: none;
+#{$adminPanel-prefix} {
+    .typo3-adminPanel-card-group {
+        display: flex;
+        margin: -5px;
+        margin-bottom: 1em;
+        flex-wrap: wrap;
 
-        &:focus,
-        &:hover,
-        &:active {
-            outline: none;
+        .typo3-adminPanel-card {
+            margin: 5px;
+            flex-grow: 1;
+            flex-shrink: 0;
+            max-width: 100%;
         }
     }
 
-    .typo3-adminPanel-btn-default {
-        color: #333;
-        background-color: #eee;
-        border-color: #bbb;
-        cursor: pointer;
+    .typo3-adminPanel-card {
+        background-color: $adminPanel-card-bg;
+        margin-bottom: 1em;
+        box-shadow: 0 0 1px rgba(0, 0, 0, 0.15);
+    }
 
-        &:hover {
-            background-color: #c4c4c4;
+    .typo3-adminPanel-card-header,
+    .typo3-adminPanel-card-body {
+        > *:first-child {
+            margin-top: 0;
+        }
+
+        > *:last-child {
+            margin-bottom: 0;
         }
     }
 
-    .typo3-adminPanel-btn-dark {
-        color: #fafafa;
-        background-color: #555;
-        border-color: rgba(0, 0, 0, 0.5);
-        cursor: pointer;
+    .typo3-adminPanel-card-header {
+        display: flex;
+        align-items: center;
+        padding: $adminPanel-card-padding;
+        padding-bottom: 0;
+    }
 
-        &:hover {
-            background-color: #444;
-        }
+    .typo3-adminPanel-card-header-headline {
+        display: flex;
+        align-items: center;
     }
 
-    .typo3-adminPanel-btn-group {
+    .typo3-adminPanel-card-header-icon {
         position: relative;
-        display: inline-block;
-        vertical-align: middle;
+        height: 1em;
+        width: 1em;
+        opacity: 0.75;
 
-        .typo3-adminPanel-btn + .typo3-adminPanel-btn {
-            margin-left: -1px;
+        .icon {
+            position: absolute;
+            top: 50%;
+            left: 50%;
+            transform: translate(-50%, -50%);
         }
     }
+
+    .typo3-adminPanel-card-header-text {
+        padding-left: 0.5em;
+        font-size: 1.25em;
+    }
+
+    .typo3-adminPanel-card-body {
+        padding: $adminPanel-card-padding;
+    }
 }
 
 //
-// Treeline
+// Dump
 //
-#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel {
-    .treeline-icon {
-        display: inline-block;
-        margin-right: 2px;
-        padding: 0;
-        height: 18px;
-        width: 16px;
-        white-space: nowrap;
-        overflow: hidden;
-        vertical-align: middle;
+#{$adminPanel-prefix} {
+    .typo3-adminPanel-dump {
+        font-family: monospace;
+        word-wrap: break-word;
+        white-space: pre-wrap;
+        position: relative;
+        z-index: 99999;
+        word-break: break-all;
     }
 
-    .treeline-icon:after,
-    .treeline-icon:before {
-        position: absolute;
-        content: '';
-        margin-left: 7px;
-    }
+    .typo3-adminPanel-dump-string {
+        color: #75a75a;
 
-    .treeline-icon:before {
-        top: 0;
-        height: 100%;
-        width: 2px;
-        margin-left: 7px;
-        border-left: 1px dotted #666;
+        &:before,
+        &:after {
+            color: #bf6500;
+            content: '"';
+        }
     }
 
-    .treeline-icon:after {
-        border-top: 1px dotted #666;
-        height: 2px;
-        width: 8px;
-        margin-top: 8px;
+    .typo3-adminPanel-dump-float,
+    .typo3-adminPanel-dump-integer {
+        color: #538bb3;
     }
+}
 
-    .treeline-icon-jointop:before {
-        top: 50%;
+//
+// Form
+//
+#{$adminPanel-prefix} {
+    .typo3-adminPanel-form-group {
+        display: block;
+        margin: 1.5em 0;
     }
 
-    .treeline-icon-joinbottom:before {
-        height: 26px;
-        margin-top: -8px;
+    .typo3-adminPanel-form-group-checkbox {
+        + .typo3-adminPanel-form-group-checkbox {
+            margin-top: -0.5em;
+        }
     }
+}
 
-    .treeline-icon-line:after {
-        display: none;
+//
+// Checkbox
+//
+#{$adminPanel-prefix} {
+    .typo3-adminPanel-form-checkbox {
+        padding-left: 1.75em;
     }
 
-    .treeline-icon-blank {
-        display: none;
+    .typo3-adminPanel-form-checkbox-label {
+        position: relative;
+        cursor: pointer;
+
+        &:before {
+            position: absolute;
+            top: 0;
+            left: -1.75em;
+            display: block;
+            width: 1.25em;
+            height: 1.25em;
+            pointer-events: none;
+            content: '';
+            user-select: none;
+            background-color: #dadada;
+            border-radius: $adminPanel-input-border-radius;
+        }
+
+        &:after {
+            position: absolute;
+            top: 0;
+            left: -1.75em;
+            display: block;
+            width: 1.25em;
+            height: 1.25em;
+            content: '';
+            background-repeat: no-repeat;
+            background-position: center center;
+            background-size: 50% 50%;
+        }
     }
 
-    .treeline-icon-clear:before,
-    .treeline-icon-clear:after {
+    .typo3-adminPanel-form-checkbox-input {
         display: none;
+
+        &:checked + .typo3-adminPanel-form-checkbox-label {
+            &:before {
+                background-color: #629755;
+            }
+
+            &:after {
+                background-image: url("data:image/svg+xml;charset=utf8, <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'><path fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/></svg>");
+            }
+        }
     }
 }
 
 //
-// Frontend Editing Styles
+// Select
 //
-.typo3-feedit-element {
-    border: 1px solid #cacaca;
-    margin: 1em 0;
+#{$adminPanel-prefix} {
+    .typo3-adminPanel-form-select {
+        .typo3-adminPanel-form-select-label {
+            margin-bottom: 0.5em;
+            display: block;
+        }
+
+        .typo3-adminPanel-form-select-input {
+            padding: $adminPanel-input-horizontal-padding 3em $adminPanel-input-horizontal-padding $adminPanel-input-vertical-padding;
+            display: block;
+            border-radius: $adminPanel-input-border-radius;
+            border: 1px solid $adminPanel-input-border;
+            background: $adminPanel-input-bg url("data:image/svg+xml;charset=utf8, <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'><path fill='#333' d='M2 0L0 2h4zm0 5L0 3h4z'/></svg>") no-repeat right 0.75em center;
+            background-size: 8px 10px;
+            appearance: none;
+
+            &:hover,
+            &:focus {
+                border: 1px solid $adminPanel-input-hover-border;
+            }
+        }
+    }
 }
 
-.typo3-editPanel {
-    @extend %basestyles;
+//
+// DateTime
+//
+#{$adminPanel-prefix} {
+    .typo3-adminPanel-form-datetime {
+        .typo3-adminPanel-form-datetime-label {
+            margin-bottom: 0.5em;
+            display: block;
+        }
 
-    display: block !important;
-    border-top: 1px solid #cacaca;
-    padding: 0.5em;
+        .typo3-adminPanel-form-datetime-input-group {
+            margin: -5px;
+            display: flex;
+            flex-wrap: wrap;
+        }
 
-    .typo3-editPanel-label {
-        margin-left: 1.5em;
-        display: inline-block;
-        vertical-align: middle;
+        .typo3-adminPanel-form-datetime-input {
+            flex-grow: 1;
+            flex-shrink: 0;
+            margin: 5px;
+            display: block;
+            padding: $adminPanel-input-horizontal-padding $adminPanel-input-vertical-padding;
+            border-radius: $adminPanel-input-border-radius;
+            border: 1px solid $adminPanel-input-border;
+            background-color: $adminPanel-input-bg;
+
+            &:hover,
+            &:focus {
+                border: 1px solid $adminPanel-input-hover-border;
+            }
+        }
     }
+}
 
-    .typo3-adminPanel-btn,
-    .typo3-editPanel-btn {
-        display: inline-block !important;
-        margin-bottom: 0;
-        padding: 6px 8px;
-        line-height: 1.5em;
-        border: 1px solid transparent;
-        border-radius: 0;
-        font-weight: normal;
-        text-align: center;
-        vertical-align: middle;
-        touch-action: manipulation;
+//
+// Button
+//
+#{$adminPanel-prefix} {
+    .typo3-adminPanel-btn {
+        position: relative;
         cursor: pointer;
-        white-space: nowrap;
-        user-select: none;
+        color: inherit;
+        text-decoration: none;
+        padding: $adminPanel-input-horizontal-padding $adminPanel-input-vertical-padding;
+        display: inline-block;
+        background-color: rgba(0, 0, 0, 0.1);
+        border: 1px solid $adminPanel-input-border;
+        border-radius: $adminPanel-input-border-radius;
 
-        &:focus,
         &:hover,
-        &:active {
-            outline: none;
+        &:focus {
+            z-index: 1;
+            background-color: rgba(0, 0, 0, 0.15);
+            border: 1px solid $adminPanel-input-hover-border;
         }
     }
 
-    .typo3-adminPanel-btn-default,
-    .typo3-editPanel-btn-default {
-        color: #333;
-        background-color: #eee;
-        border-color: #bbb;
-        cursor: pointer;
+    .typo3-adminPanel-btn-primary {
+        color: #fff;
+        background-color: #538bb3;
+        border: 1px solid darken(#538bb3, 10%);
 
-        &:hover {
-            background-color: #c4c4c4;
+        &:hover,
+        &:focus {
+            background-color: lighten(#538bb3, 5%);
+            border: 1px solid darken(#538bb3, 15%);
         }
     }
 
-    .typo3-adminPanel-form-group,
-    .typo3-editPanel-form-group {
-        margin-right: 0.5em;
-        display: inline-block;
-    }
-
-    .typo3-adminPanel-btn-group,
-    .typo3-editPanel-btn-group {
-        position: relative;
-        display: inline-block;
-        vertical-align: middle;
-
-        .typo3-adminPanel-btn + .typo3-adminPanel-btn,
-        .typo3-editPanel-btn + .typo3-editPanel-btn {
-            margin-left: -1px;
+    .typo3-adminPanel-btn-group {
+        &:after {
+            content: '';
+            display: table;
+            clear: both;
         }
-    }
-}
 
-.typo3-adminPanel-btn,
-.typo3-editPanel-btn {
-    display: inline-block !important;
-}
-
-.typo3-feedit-element-hidden {
-    border-color: darken(#f8ecce, 20%);
+        .typo3-adminPanel-btn {
+            border-radius: 0;
+            float: left;
 
-    .typo3-editPanel {
-        border-top-color: darken(#f8ecce, 20%);
-        background-color: #f8ecce;
+            &:first-child {
+                border-radius: $adminPanel-input-border-radius 0 0 $adminPanel-input-border-radius;
+            }
 
-        .typo3-editPanel-btn-default {
-            border-color: darken(#f8ecce, 30%);
-            background-color: darken(#f8ecce, 10%);
+            &:last-child {
+                border-radius: 0 $adminPanel-input-border-radius $adminPanel-input-border-radius 0;
+            }
 
-            &:hover {
-                background-color: darken(#f8ecce, 15%);
+            & + .typo3-adminPanel-btn {
+                margin-left: -1px;
             }
         }
     }
index a870271..23db002 100644 (file)
@@ -16,12 +16,11 @@ namespace TYPO3\CMS\Adminpanel\Controller;
  * The TYPO3 project - inspiring people to share!
  */
 
-use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ServerRequestInterface;
+use TYPO3\CMS\Adminpanel\Service\ConfigurationService;
 use TYPO3\CMS\Adminpanel\Service\ModuleLoader;
 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
-use TYPO3\CMS\Core\Cache\CacheManager;
 use TYPO3\CMS\Core\Http\JsonResponse;
-use TYPO3\CMS\Core\Http\ServerRequest;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
@@ -29,52 +28,55 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
  */
 class AjaxController
 {
+    /**
+     * @var array
+     */
+    protected $adminPanelModuleConfiguration;
+
+    /**
+     * @var \TYPO3\CMS\Adminpanel\Service\ModuleLoader
+     */
+    protected $moduleLoader;
+
+    /**
+     * @var \TYPO3\CMS\Adminpanel\Service\ConfigurationService
+     */
+    private $configurationService;
+
+    /**
+     * @param ConfigurationService $configurationService
+     * @param ModuleLoader $moduleLoader
+     */
+    public function __construct(ConfigurationService $configurationService = null, ModuleLoader $moduleLoader = null)
+    {
+        $this->configurationService = $configurationService
+                                      ??
+                                      GeneralUtility::makeInstance(ConfigurationService::class);
+        $this->adminPanelModuleConfiguration = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules'] ?? [];
+        $this->moduleLoader = $moduleLoader ?? GeneralUtility::makeInstance(ModuleLoader::class);
+    }
 
     /**
      * Save adminPanel data
      *
-     * @param ServerRequest $request
+     * @param ServerRequestInterface $request
      * @return JsonResponse
      */
-    public function saveDataAction(ServerRequest $request): JsonResponse
+    public function saveDataAction(ServerRequestInterface $request): JsonResponse
     {
-        $moduleLoader = GeneralUtility::makeInstance(ModuleLoader::class);
-
-        $modules = $moduleLoader->getModulesFromConfiguration();
-
-        $input = $request->getParsedBody()['TSFE_ADMIN_PANEL'] ?? null;
-        $beUser = $this->getBackendUser();
-        if (is_array($input)) {
-            // Setting
-            $beUser->uc['TSFE_adminConfig'] = array_merge(
-                !is_array($beUser->uc['TSFE_adminConfig']) ? [] : $beUser->uc['TSFE_adminConfig'],
-                $input
-            );
-            unset($beUser->uc['TSFE_adminConfig']['action']);
-
-            /** @var \TYPO3\CMS\Adminpanel\Modules\AdminPanelModuleInterface $module */
-            foreach ($modules as $module) {
-                if ($module->isEnabled()) {
-                    $module->onSubmit($input);
-                }
-            }
-            // Saving
-            $beUser->writeUC();
-            // Flush fluid template cache
-            $cacheManager = GeneralUtility::makeInstance(CacheManager::class);
-            $cacheManager->setCacheConfigurations($GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']);
-            $cacheManager->getCache('fluid_template')->flush();
-        }
+        $this->configurationService->saveConfiguration(
+            $this->moduleLoader->validateSortAndInitializeModules($this->adminPanelModuleConfiguration),
+            $request
+        );
         return new JsonResponse(['success' => true]);
     }
 
     /**
      * Toggle admin panel active state via UC
      *
-     * @param \Psr\Http\Message\RequestInterface $request
      * @return \TYPO3\CMS\Core\Http\JsonResponse
      */
-    public function toggleActiveState(RequestInterface $request): JsonResponse
+    public function toggleActiveState(): JsonResponse
     {
         $backendUser = $this->getBackendUser();
         if ($backendUser->uc['TSFE_adminConfig']['display_top'] ?? false) {
index 2df560c..95accbe 100644 (file)
@@ -16,15 +16,18 @@ namespace TYPO3\CMS\Adminpanel\Controller;
  * The TYPO3 project - inspiring people to share!
  */
 
+use Psr\Http\Message\ServerRequestInterface;
 use TYPO3\CMS\Adminpanel\Modules\AdminPanelModuleInterface;
+use TYPO3\CMS\Adminpanel\Service\ConfigurationService;
 use TYPO3\CMS\Adminpanel\Service\ModuleLoader;
 use TYPO3\CMS\Adminpanel\View\AdminPanelView;
 use TYPO3\CMS\Backend\FrontendBackendUserAuthentication;
-use TYPO3\CMS\Core\Cache\CacheManager;
-use TYPO3\CMS\Core\Http\ServerRequest;
+use TYPO3\CMS\Backend\Routing\UriBuilder;
 use TYPO3\CMS\Core\Localization\LanguageService;
 use TYPO3\CMS\Core\SingletonInterface;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Core\Utility\PathUtility;
+use TYPO3\CMS\Fluid\View\StandaloneView;
 use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
 
 /**
@@ -35,80 +38,166 @@ use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
 class MainController implements SingletonInterface
 {
     /**
-     * @var array<AdminPanelModuleInterface>
+     * @var AdminPanelModuleInterface[]
      */
     protected $modules = [];
 
     /**
+     * @var ModuleLoader
+     */
+    protected $moduleLoader;
+
+    /**
+     * @var UriBuilder
+     */
+    protected $uriBuilder;
+
+    /**
+     * @var ConfigurationService
+     */
+    protected $configurationService;
+
+    /**
+     * @var array
+     */
+    private $adminPanelModuleConfiguration;
+
+    /**
+     * @param ModuleLoader $moduleLoader
+     * @param UriBuilder $uriBuilder
+     * @param ConfigurationService $configurationService
+     */
+    public function __construct(
+        ModuleLoader $moduleLoader = null,
+        UriBuilder $uriBuilder = null,
+        ConfigurationService $configurationService = null
+    ) {
+        $this->moduleLoader = $moduleLoader ?? GeneralUtility::makeInstance(ModuleLoader::class);
+        $this->uriBuilder = $uriBuilder ?? GeneralUtility::makeInstance(UriBuilder::class);
+        $this->configurationService = $configurationService ?? GeneralUtility::makeInstance(ConfigurationService::class);
+        $this->adminPanelModuleConfiguration = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules'] ?? [];
+    }
+
+    /**
      * Initializes settings for the admin panel.
      *
-     * @param \TYPO3\CMS\Core\Http\ServerRequest $request
+     * @param ServerRequestInterface $request
      */
-    public function initialize(ServerRequest $request): void
+    public function initialize(ServerRequestInterface $request): void
     {
-        $moduleLoader = GeneralUtility::makeInstance(ModuleLoader::class);
-        $this->modules = $moduleLoader->getModulesFromConfiguration();
-        $this->saveConfiguration();
+        $this->modules = $this->moduleLoader->validateSortAndInitializeModules(
+            $this->adminPanelModuleConfiguration
+        );
+        $this->configurationService->saveConfiguration($this->modules, $request);
 
-        foreach ($this->modules as $module) {
-            if ($module->isEnabled()) {
-                $module->initializeModule($request);
+        if ($this->isAdminPanelActivated()) {
+            foreach ($this->modules as $module) {
+                if ($module->isEnabled()) {
+                    $subModules = $this->moduleLoader->validateSortAndInitializeSubModules(
+                        $this->adminPanelModuleConfiguration[$module->getIdentifier()]['submodules'] ?? []
+                    );
+                    foreach ($subModules as $subModule) {
+                        $subModule->initializeModule($request);
+                    }
+                    $module->setSubModules($subModules);
+                    $module->initializeModule($request);
+                }
             }
         }
     }
 
     /**
-     * Renders the panel - Is currently called via RenderHook in postProcessOutput
-     *
-     * @todo Still uses the legacy AdminpanelView and should be rewritten to fluid
+     * Renders the admin panel
      *
      * @return string
      */
     public function render(): string
     {
-        // handling via legacy functions
+        // legacy handling
         $adminPanelView = GeneralUtility::makeInstance(AdminPanelView::class);
-        $adminPanelView->setModules($this->modules);
-        return $adminPanelView->display();
+        $hookObjectContent = $adminPanelView->callDeprecatedHookObject();
+        // end legacy handling
+
+        $resources = $this->getResources();
+
+        $view = GeneralUtility::makeInstance(StandaloneView::class);
+        $templateNameAndPath = 'EXT:adminpanel/Resources/Private/Templates/Main.html';
+        $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName($templateNameAndPath));
+        $view->setPartialRootPaths(['EXT:adminpanel/Resources/Private/Partials']);
+        $view->setLayoutRootPaths(['EXT:adminpanel/Resources/Private/Layouts']);
+
+        $view->assignMultiple(
+            [
+                'toggleActiveUrl' => $this->generateBackendUrl('ajax_adminPanel_toggle'),
+                'resources' => $resources,
+                'adminPanelActive' => $this->isAdminPanelActivated(),
+            ]
+        );
+        if ($this->isAdminPanelActivated()) {
+            $moduleResources = $this->getAdditionalResourcesForModules($this->modules);
+            $view->assignMultiple(
+                [
+                    'modules' => $this->modules,
+                    'hookObjectContent' => $hookObjectContent,
+                    'saveUrl' => $this->generateBackendUrl('ajax_adminPanel_saveForm'),
+                    'moduleResources' => $moduleResources,
+                ]
+            );
+        }
+
+        return $view->render();
     }
 
     /**
-     * Save admin panel configuration to backend user UC
+     * Generate a url to a backend route
+     *
+     * @param string $route
+     * @return string
      */
-    protected function saveConfiguration(): void
+    protected function generateBackendUrl(string $route): string
     {
-        $input = GeneralUtility::_GP('TSFE_ADMIN_PANEL');
-        $beUser = $this->getBackendUser();
-        if (is_array($input)) {
-            // Setting
-            $beUser->uc['TSFE_adminConfig'] = array_merge(
-                !is_array($beUser->uc['TSFE_adminConfig']) ? [] : $beUser->uc['TSFE_adminConfig'],
-                $input
-            );
-            unset($beUser->uc['TSFE_adminConfig']['action']);
+        return (string)$this->uriBuilder->buildUriFromRoute($route);
+    }
 
-            foreach ($this->modules as $module) {
-                if ($module->isEnabled() && $module->isOpen()) {
-                    $module->onSubmit($input);
-                }
+    /**
+     * Get additional resources (css, js) from modules and merge it to
+     * one array - returns an array of full html tags
+     *
+     * @param AdminPanelModuleInterface[] $modules
+     * @return array
+     */
+    protected function getAdditionalResourcesForModules(array $modules): array
+    {
+        $result = [
+            'js' => '',
+            'css' => '',
+        ];
+        foreach ($modules as $module) {
+            foreach ($module->getJavaScriptFiles() as $file) {
+                $result['js'] .= $this->getJsTag($file);
+            }
+            foreach ($module->getCssFiles() as $file) {
+                $result['css'] .= $this->getCssTag($file);
             }
-            // Saving
-            $beUser->writeUC();
-            // Flush fluid template cache
-            $cacheManager = new CacheManager();
-            $cacheManager->setCacheConfigurations($GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']);
-            $cacheManager->getCache('fluid_template')->flush();
         }
+        return $result;
     }
 
     /**
-     * Returns LanguageService
+     * Returns a link tag with the admin panel stylesheet
+     * defined using TBE_STYLES
      *
-     * @return LanguageService
+     * @return string
      */
-    protected function getLanguageService(): LanguageService
+    protected function getAdminPanelStylesheet(): string
     {
-        return $GLOBALS['LANG'];
+        $result = '';
+        if (!empty($GLOBALS['TBE_STYLES']['stylesheets']['admPanel'])) {
+            $stylesheet = GeneralUtility::locationHeaderUrl($GLOBALS['TBE_STYLES']['stylesheets']['admPanel']);
+            $result = '<link rel="stylesheet" type="text/css" href="' .
+                      htmlspecialchars($stylesheet, ENT_QUOTES | ENT_HTML5) . '" />';
+        }
+        return $result;
     }
 
     /**
@@ -122,10 +211,80 @@ class MainController implements SingletonInterface
     }
 
     /**
+     * Get a css tag for file - with absolute web path resolving
+     *
+     * @param string $cssFileLocation
+     * @return string
+     */
+    protected function getCssTag(string $cssFileLocation): string
+    {
+        $css = '<link type="text/css" rel="stylesheet" href="' .
+               htmlspecialchars(
+                   PathUtility::getAbsoluteWebPath(GeneralUtility::getFileAbsFileName($cssFileLocation)),
+                   ENT_QUOTES | ENT_HTML5
+               ) .
+               '" media="all" />';
+        return $css;
+    }
+
+    /**
+     * Get a script tag for JavaScript with absolute paths
+     *
+     * @param string $jsFileLocation
+     * @return string
+     */
+    protected function getJsTag(string $jsFileLocation): string
+    {
+        $js = '<script type="text/javascript" src="' .
+              htmlspecialchars(
+                  PathUtility::getAbsoluteWebPath(GeneralUtility::getFileAbsFileName($jsFileLocation)),
+                  ENT_QUOTES | ENT_HTML5
+              ) .
+              '"></script>';
+        return $js;
+    }
+
+    /**
+     * Returns LanguageService
+     *
+     * @return LanguageService
+     */
+    protected function getLanguageService(): LanguageService
+    {
+        return $GLOBALS['LANG'];
+    }
+
+    /**
+     * Return a string with tags for main admin panel resources
+     *
+     * @return string
+     */
+    protected function getResources(): string
+    {
+        $jsFileLocation = 'EXT:adminpanel/Resources/Public/JavaScript/AdminPanel.js';
+        $js = $this->getJsTag($jsFileLocation);
+        $cssFileLocation = 'EXT:adminpanel/Resources/Public/Css/adminpanel.css';
+        $css = $this->getCssTag($cssFileLocation);
+
+        return $css . $this->getAdminPanelStylesheet() . $js;
+    }
+
+    /**
      * @return TypoScriptFrontendController
      */
     protected function getTypoScriptFrontendController(): TypoScriptFrontendController
     {
         return $GLOBALS['TSFE'];
     }
+
+    /**
+     * Returns true if admin panel was activated
+     * (switched "on" via GUI)
+     *
+     * @return bool
+     */
+    protected function isAdminPanelActivated(): bool
+    {
+        return (bool)($this->getBackendUser()->uc['TSFE_adminConfig']['display_top'] ?? false);
+    }
 }
index a92269f..09c45ee 100644 (file)
@@ -26,26 +26,25 @@ use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
  */
 class RenderHook
 {
-
     /**
      * Hook to render the admin panel
      * We use a hook this late in the project to make sure all data is collected and can be displayed
-     *
      * As the main content is already rendered, we use a string replace on the content to append the adminPanel
      * to the HTML body.
      *
      * @param array $params
      * @param TypoScriptFrontendController $pObj
      */
-    public function renderAdminPanel(array $params, TypoScriptFrontendController $pObj)
+    public function renderAdminPanel(array $params, TypoScriptFrontendController $pObj): void
     {
-        if ($pObj->isBackendUserLoggedIn() &&
+        if (
+            $pObj->isBackendUserLoggedIn() &&
             $GLOBALS['BE_USER'] instanceof FrontendBackendUserAuthentication &&
-            (
-                !$GLOBALS['BE_USER']->extAdminConfig['hide'] && $pObj->config['config']['admPanel']
-            )
+            isset($GLOBALS['BE_USER']->getTSConfig()['admPanel.']['enable.']) &&
+            !$GLOBALS['BE_USER']->extAdminConfig['hide'] && $pObj->config['config']['admPanel']
         ) {
             $mainController = GeneralUtility::makeInstance(MainController::class);
+
             $pObj->content = str_ireplace(
                 '</body>',
                 $mainController->render() . '</body>',
index b36880f..19f0f73 100644 (file)
@@ -30,7 +30,6 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
  */
 class AdminPanelInitiator implements MiddlewareInterface
 {
-
     /**
      * Initialize the adminPanel if
      * - backend user is logged in
index a66fa8f..84e8a2b 100644 (file)
@@ -16,14 +16,17 @@ namespace TYPO3\CMS\Adminpanel\Modules;
  * The TYPO3 project - inspiring people to share!
  */
 
+use Psr\Http\Message\ServerRequestInterface;
+use TYPO3\CMS\Adminpanel\Service\ConfigurationService;
 use TYPO3\CMS\Backend\FrontendBackendUserAuthentication;
-use TYPO3\CMS\Core\Http\ServerRequest;
+use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
 use TYPO3\CMS\Core\Localization\LanguageService;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
- * Abstract base class for Core Admin Panel Modules containing helper methods
+ * Abstract base class for Admin Panel Modules containing helper methods and default interface implementations
  *
- * @internal
+ * Extend this class when writing own admin panel modules (or implement the Interface directly)
  */
 abstract class AbstractModule implements AdminPanelModuleInterface
 {
@@ -33,19 +36,40 @@ abstract class AbstractModule implements AdminPanelModuleInterface
     protected $extResources = 'EXT:adminpanel/Resources/Private';
 
     /**
+     * @var \TYPO3\CMS\Adminpanel\Modules\AdminPanelSubModuleInterface[]
+     */
+    protected $subModules = [];
+
+    /**
+     * Main Configuration (from UserTSConfig, admPanel)
+     *
      * @var array
      */
     protected $mainConfiguration;
 
+    /**
+     * @var \TYPO3\CMS\Adminpanel\Service\ConfigurationService
+     */
+    protected $configurationService;
+
     public function __construct()
     {
-        $this->mainConfiguration = $this->getBackendUser()->getTSConfig()['admPanel.'] ?? [];
+        $this->configurationService = GeneralUtility::makeInstance(ConfigurationService::class);
+        $this->mainConfiguration = $this->configurationService->getMainConfiguration();
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function getSettings(): string
+    {
+        return '';
     }
 
     /**
      * @inheritdoc
      */
-    public function getAdditionalJavaScriptCode(): string
+    public function getIconIdentifier(): string
     {
         return '';
     }
@@ -53,13 +77,13 @@ abstract class AbstractModule implements AdminPanelModuleInterface
     /**
      * @inheritdoc
      */
-    public function initializeModule(ServerRequest $request): void
+    public function initializeModule(ServerRequestInterface $request): void
     {
     }
 
     /**
      * Returns true if the module is
-     * -> either enabled via tsconfig admPanel.enable
+     * -> either enabled via TSConfig admPanel.enable
      * -> or any setting is overridden
      * override is a way to use functionality of the admin panel without displaying the admin panel to users
      * for example: hidden records or pages can be displayed by default
@@ -77,49 +101,16 @@ abstract class AbstractModule implements AdminPanelModuleInterface
     }
 
     /**
-     * Uses the backend user session to determine if the module is open
-     *
-     * @return bool
-     */
-    public function isOpen(): bool
-    {
-        $option = 'display_' . $this->getIdentifier();
-        return isset($this->getBackendUser()->uc['TSFE_adminConfig'][$option])
-            ? (bool)$this->getBackendUser()->uc['TSFE_adminConfig'][$option]
-            : false;
-    }
-
-    /**
-     * Determines if the panel for this module is shown
-     * -> returns true if panel is enabled in TSConfig
-     *
-     * @see isEnabled()
-     * @return bool
-     */
-    public function isShown(): bool
-    {
-        return $this->isEnabledViaTsConfig();
-    }
-
-    /**
-     * @inheritdoc
-     */
-    public function onSubmit(array $input): void
-    {
-    }
-
-    /**
      * @inheritdoc
      */
-    public function showFormSubmitButton(): bool
+    public function onSubmit(array $input, ServerRequestInterface $request): void
     {
-        return false;
     }
 
     /**
      * Translate given key
      *
-     * @param string $key Key for a label in the $LOCAL_LANG array of "sysext/core/Resources/Private/Language/locallang_tsfe.xlf
+     * @param string $key Key for a label in the $LOCAL_LANG array of "sysext/lang/Resources/Private/Language/locallang_tsfe.xlf
      * @param bool $convertWithHtmlspecialchars If TRUE the language-label will be sent through htmlspecialchars
      * @return string The value for the $key
      */
@@ -135,35 +126,14 @@ abstract class AbstractModule implements AdminPanelModuleInterface
     /**
      * Returns the current BE user.
      *
-     * @return \TYPO3\CMS\Backend\FrontendBackendUserAuthentication
+     * @return BackendUserAuthentication|FrontendBackendUserAuthentication
      */
-    protected function getBackendUser(): FrontendBackendUserAuthentication
+    protected function getBackendUser(): BackendUserAuthentication
     {
         return $GLOBALS['BE_USER'];
     }
 
     /**
-     * Helper method to return configuration options
-     * Checks User TSConfig overrides and current backend user session
-     *
-     * @param string $option
-     * @return string
-     */
-    protected function getConfigurationOption(string $option): string
-    {
-        $beUser = $this->getBackendUser();
-        $identifier = $this->getIdentifier();
-
-        if ($option && isset($this->mainConfiguration['override.'][$identifier . '.'][$option])) {
-            $returnValue = $this->mainConfiguration['override.'][$identifier . '.'][$option];
-        } else {
-            $returnValue = $beUser->uc['TSFE_adminConfig'][$identifier . '_' . $option] ?? '';
-        }
-
-        return (string)$returnValue;
-    }
-
-    /**
      * Returns LanguageService
      *
      * @return \TYPO3\CMS\Core\Localization\LanguageService
@@ -197,4 +167,49 @@ abstract class AbstractModule implements AdminPanelModuleInterface
     {
         return [];
     }
+
+    /**
+     * @inheritdoc
+     */
+    public function getCssFiles(): array
+    {
+        return [];
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function getShortInfo(): string
+    {
+        return '';
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function setSubModules(array $subModules): void
+    {
+        $this->subModules = $subModules;
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function getSubModules(): array
+    {
+        return $this->subModules;
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function getHasSubmoduleSettings(): bool
+    {
+        foreach ($this->subModules as $subModule) {
+            if (!empty($subModule->getSettings())) {
+                return true;
+            }
+        }
+        return false;
+    }
 }
diff --git a/typo3/sysext/adminpanel/Classes/Modules/AbstractSubModule.php b/typo3/sysext/adminpanel/Classes/Modules/AbstractSubModule.php
new file mode 100644 (file)
index 0000000..ca409b3
--- /dev/null
@@ -0,0 +1,60 @@
+<?php
+declare(strict_types = 1);
+
+namespace TYPO3\CMS\Adminpanel\Modules;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use Psr\Http\Message\ServerRequestInterface;
+use TYPO3\CMS\Core\Localization\LanguageService;
+
+/**
+ * Abstract SubModule - Base class for sub modules in the admin panel
+ *
+ * Extend this class when writing own sub modules
+ */
+abstract class AbstractSubModule implements AdminPanelSubModuleInterface
+{
+    /**
+     * @inheritdoc
+     */
+    public function getSettings(): string
+    {
+        return '';
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function initializeModule(ServerRequestInterface $request): void
+    {
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function onSubmit(array $configurationToSave, ServerRequestInterface $request): void
+    {
+    }
+
+    /**
+     * Returns LanguageService
+     *
+     * @return \TYPO3\CMS\Core\Localization\LanguageService
+     */
+    protected function getLanguageService(): LanguageService
+    {
+        return $GLOBALS['LANG'];
+    }
+}
index f56445f..fee19e0 100644 (file)
@@ -16,53 +16,53 @@ namespace TYPO3\CMS\Adminpanel\Modules;
  * The TYPO3 project - inspiring people to share!
  */
 
-use TYPO3\CMS\Core\Http\ServerRequest;
+use Psr\Http\Message\ServerRequestInterface;
 
 /**
  * Interface for admin panel modules registered via EXTCONF
- *
- * @internal until API is stable
  */
 interface AdminPanelModuleInterface
 {
-
     /**
-     * Additional JavaScript code for this module
-     * (you should only use vanilla JS here, as you cannot
-     * rely on the web site providing a specific framework)
+     * Identifier for this module,
+     * for example "preview" or "cache"
      *
      * @return string
      */
-    public function getAdditionalJavaScriptCode(): string;
+    public function getIdentifier(): string;
 
     /**
-     * Module content as rendered HTML
+     * Module label
      *
      * @return string
      */
-    public function getContent(): string;
+    public function getLabel(): string;
 
     /**
-     * Identifier for this module,
-     * for example "preview" or "cache"
+     * Module Icon identifier - needs to be registered in iconRegistry
      *
      * @return string
      */
-    public function getIdentifier(): string;
+    public function getIconIdentifier(): string;
 
     /**
-     * Module label
+     * Displayed directly in the bar if module has content
      *
      * @return string
      */
-    public function getLabel(): string;
+    public function getShortInfo(): string;
+
+    /**
+     * @return string
+     */
+    public function getSettings(): string;
 
     /**
      * Initialize the module - runs early in a TYPO3 request
      *
-     * @param \TYPO3\CMS\Core\Http\ServerRequest $request
+     * @param ServerRequestInterface $request
      */
-    public function initializeModule(ServerRequest $request): void;
+    public function initializeModule(ServerRequestInterface $request): void;
 
     /**
      * Module is enabled
@@ -76,43 +76,47 @@ interface AdminPanelModuleInterface
     public function isEnabled(): bool;
 
     /**
-     * Module is open
-     * -> module is enabled
-     * -> module panel is shown and open
+     * Executed on saving / submit of the configuration form
+     * Can be used to react to changed settings
+     * (for example: clearing a specific cache)
      *
-     * @return bool
+     * @param array $configurationToSave
+     * @param ServerRequestInterface $request
      */
-    public function isOpen(): bool;
+    public function onSubmit(array $configurationToSave, ServerRequestInterface $request): void;
 
     /**
-     * Module is shown
-     * -> module is enabled
-     * -> module panel should be displayed
+     * Returns a string array with javascript files that will be rendered after the module
      *
-     * @return bool
+     * @return array
      */
-    public function isShown(): bool;
+    public function getJavaScriptFiles(): array;
 
     /**
-     * Executed on saving / submit of the configuration form
-     * Can be used to react to changed settings
-     * (for example: clearing a specific cache)
+     * Returns a string array with css files that will be rendered after the module
+     *
+     * @return array
+     */
+    public function getCssFiles(): array;
+
+    /**
+     * Set SubModules for current module
      *
-     * @param array $input
+     * @param AdminPanelSubModuleInterface[] $subModules
      */
-    public function onSubmit(array $input): void;
+    public function setSubModules(array $subModules): void;
 
     /**
-     * Does this module need a form submit?
+     * Get SubModules for current module
      *
-     * @return bool
+     * @return AdminPanelSubModuleInterface[]
      */
-    public function showFormSubmitButton(): bool;
+    public function getSubModules(): array;
 
     /**
-     * Returns a string array with javascript files that will be rendered after the module
+     * Returns true if submodule has own settings
      *
-     * @return array
+     * @return bool
      */
-    public function getJavaScriptFiles(): array;
+    public function getHasSubmoduleSettings(): bool;
 }
diff --git a/typo3/sysext/adminpanel/Classes/Modules/AdminPanelSubModuleInterface.php b/typo3/sysext/adminpanel/Classes/Modules/AdminPanelSubModuleInterface.php
new file mode 100644 (file)
index 0000000..ba2aa5e
--- /dev/null
@@ -0,0 +1,72 @@
+<?php
+declare(strict_types = 1);
+
+namespace TYPO3\CMS\Adminpanel\Modules;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use Psr\Http\Message\ServerRequestInterface;
+
+/**
+ * Interface for admin panel sub modules registered via EXTCONF
+ */
+interface AdminPanelSubModuleInterface
+{
+
+    /**
+     * Initialize the module - runs early in a TYPO3 request
+     *
+     * @param ServerRequestInterface $request
+     */
+    public function initializeModule(ServerRequestInterface $request): void;
+
+    /**
+     * Identifier for this Sub-module,
+     * for example "preview" or "cache"
+     *
+     * @return string
+     */
+    public function getIdentifier(): string;
+
+    /**
+     * Sub-Module label
+     *
+     * @return string
+     */
+    public function getLabel(): string;
+
+    /**
+     * Sub-Module content as rendered HTML
+     *
+     * @return string
+     */
+    public function getContent(): string;
+
+    /**
+     * Settings as HTML form elements (without wrapping form tag or save button)
+     *
+     * @return string
+     */
+    public function getSettings(): string;
+
+    /**
+     * Executed on saving / submit of the configuration form
+     * Can be used to react to changed settings
+     * (for example: clearing a specific cache)
+     *
+     * @param array $configurationToSave
+     * @param ServerRequestInterface $request
+     */
+    public function onSubmit(array $configurationToSave, ServerRequestInterface $request): void;
+}
index 78c8606..73abfd6 100644 (file)
@@ -16,8 +16,8 @@ namespace TYPO3\CMS\Adminpanel\Modules;
  * The TYPO3 project - inspiring people to share!
  */
 
-use TYPO3\CMS\Core\Http\ServerRequest;
-use TYPO3\CMS\Core\Type\Bitmask\Permission;
+use Psr\Http\Message\ServerRequestInterface;
+use TYPO3\CMS\Backend\Routing\UriBuilder;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Fluid\View\StandaloneView;
 use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
@@ -25,23 +25,40 @@ use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
 class CacheModule extends AbstractModule
 {
     /**
-     * Creates the content for the "cache" section ("module") of the Admin Panel
-     *
-     * @return string HTML content for the section. Consists of a string with table-rows with four columns.
+     * @return string
      */
-    public function getContent(): string
+    public function getIconIdentifier(): string
+    {
+        return 'apps-toolbar-menu-cache';
+    }
+
+    /**
+     * @return string
+     */
+    public function getSettings(): string
     {
         $view = GeneralUtility::makeInstance(StandaloneView::class);
-        $templateNameAndPath = $this->extResources . '/Templates/Modules/Cache.html';
+        $templateNameAndPath = $this->extResources . '/Templates/Modules/Settings/Cache.html';
         $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName($templateNameAndPath));
         $view->setPartialRootPaths([$this->extResources . '/Partials']);
 
-        $view->assignMultiple([
-            'isEnabled' => $this->getBackendUser()->uc['TSFE_adminConfig']['display_cache'],
-            'noCache' => $this->getBackendUser()->uc['TSFE_adminConfig']['cache_noCache'],
-            'cacheLevels' => $this->getBackendUser()->uc['TSFE_adminConfig']['cache_clearCacheLevels'],
-            'currentId' => $this->getTypoScriptFrontendController()->id
-        ]);
+        $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
+        $feCacheClear = $this->getBackendUser()->isAdmin() || $this->getBackendUser()->getTSConfig()['options.']['clearCache.']['pages'];
+
+        $view->assignMultiple(
+            [
+                'isEnabled' => $this->getBackendUser()->uc['TSFE_adminConfig']['display_cache'],
+                'noCache' => $this->getBackendUser()->uc['TSFE_adminConfig']['cache_noCache'],
+                'currentId' => $this->getTypoScriptFrontendController()->id,
+                'clearPageCacheUrl' => $feCacheClear ? (string)$uriBuilder->buildUriFromRoute('tce_db', ['cacheCmd' => 'pages']) : '',
+                'clearCurrentPageCacheUrl' => (string)$uriBuilder->buildUriFromRoute(
+                    'tce_db',
+                    [
+                        'cacheCmd' => $this->getTypoScriptFrontendController()->id,
+                    ]
+                ),
+            ]
+        );
 
         return $view->render();
     }
@@ -66,47 +83,26 @@ class CacheModule extends AbstractModule
     /**
      * @inheritdoc
      */
-    public function initializeModule(ServerRequest $request): void
+    public function initializeModule(ServerRequestInterface $request): void
     {
-        if ($this->getConfigurationOption('noCache')) {
+        if ($this->configurationService->getConfigurationOption('cache', 'noCache')) {
             $this->getTypoScriptFrontendController()->set_no_cache('Admin Panel: No Caching', true);
         }
     }
 
     /**
-     * Clear cache on saving if requested
-     *
-     * @param array $input
-     */
-    public function onSubmit(array $input): void
-    {
-        if (($input['action']['clearCache'] ?? false) || isset($input['preview_showFluidDebug'])) {
-            $theStartId = (int)$input['cache_clearCacheId'];
-            $this->getTypoScriptFrontendController()
-                ->clearPageCacheContent_pidList(
-                    $this->getBackendUser()->extGetTreeList(
-                        $theStartId,
-                        (int)$this->getConfigurationOption('clearCacheLevels'),
-                        0,
-                        $this->getBackendUser()->getPagePermsClause(Permission::PAGE_SHOW)
-                    ) . $theStartId
-                );
-        }
-    }
-
-    /**
-     * @inheritdoc
+     * @return TypoScriptFrontendController
      */
-    public function showFormSubmitButton(): bool
+    protected function getTypoScriptFrontendController(): TypoScriptFrontendController
     {
-        return true;
+        return $GLOBALS['TSFE'];
     }
 
     /**
-     * @return TypoScriptFrontendController
+     * @return array
      */
-    protected function getTypoScriptFrontendController(): TypoScriptFrontendController
+    public function getJavaScriptFiles(): array
     {
-        return $GLOBALS['TSFE'];
+        return ['EXT:adminpanel/Resources/Public/JavaScript/Modules/Cache.js'];
     }
 }
index 56e194a..90343e0 100644 (file)
@@ -16,9 +16,9 @@ namespace TYPO3\CMS\Adminpanel\Modules;
  * The TYPO3 project - inspiring people to share!
  */
 
+use Psr\Http\Message\ServerRequestInterface;
 use TYPO3\CMS\Adminpanel\Service\EditToolbarService;
 use TYPO3\CMS\Backend\Utility\BackendUtility;
-use TYPO3\CMS\Core\Http\ServerRequest;
 use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Fluid\View\StandaloneView;
@@ -34,30 +34,30 @@ class EditModule extends AbstractModule
      *
      * @return string HTML content for the section. Consists of a string with table-rows with four columns.
      */
-    public function getContent(): string
+    public function getSettings(): string
     {
+        $editToolbarService = GeneralUtility::makeInstance(EditToolbarService::class);
+        $toolbar = $editToolbarService->createToolbar();
         $view = GeneralUtility::makeInstance(StandaloneView::class);
-        $templateNameAndPath = $this->extResources . '/Templates/Modules/Edit.html';
+        $templateNameAndPath = $this->extResources . '/Templates/Modules/Settings/Edit.html';
         $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName($templateNameAndPath));
         $view->setPartialRootPaths([$this->extResources . '/Partials']);
-
-        $editToolbarService = GeneralUtility::makeInstance(EditToolbarService::class);
-        $view->assignMultiple([
-            'feEdit' => ExtensionManagementUtility::isLoaded('feedit'),
-            'display' => [
-                'edit' => $this->getBackendUser()->uc['TSFE_adminConfig']['display_edit'],
-                'fieldIcons' => $this->getConfigurationOption('displayFieldIcons'),
-                'displayIcons' => $this->getConfigurationOption('displayIcons'),
-            ],
-            'toolbar' => $editToolbarService->createToolbar(),
-            'script' => [
-                'pageUid' => (int)$this->getTypoScriptFrontendController()->page['uid'],
-                'pageModule' => $this->getPageModule(),
-                'backendScript' => BackendUtility::getBackendScript(),
-                't3BeSitenameMd5' => \md5('Typo3Backend-' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename']),
-            ],
-        ]);
-
+        $view->assignMultiple(
+            [
+                'feEdit' => ExtensionManagementUtility::isLoaded('feedit'),
+                'display' => [
+                    'fieldIcons' => $this->configurationService->getConfigurationOption('edit', 'displayFieldIcons'),
+                    'displayIcons' => $this->configurationService->getConfigurationOption('edit', 'displayIcons'),
+                ],
+                'toolbar' => $toolbar,
+                'script' => [
+                    'pageUid' => (int)$this->getTypoScriptFrontendController()->page['uid'],
+                    'pageModule' => $this->getPageModule(),
+                    'backendScript' => BackendUtility::getBackendScript(),
+                    't3BeSitenameMd5' => md5('Typo3Backend-' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename']),
+                ],
+            ]
+        );
         return $view->render();
     }
 
@@ -74,7 +74,7 @@ class EditModule extends AbstractModule
      */
     private function getPageModule(): string
     {
-        $pageModule = \trim($this->getBackendUser()->getTSConfig()['options.']['overridePageModule'] ?? '');
+        $pageModule = trim($this->getBackendUser()->getTSConfig()['options.']['overridePageModule'] ?? '');
         return BackendUtility::isModuleSetInTBE_MODULES($pageModule) ? $pageModule : 'web_layout';
     }
 
@@ -89,25 +89,34 @@ class EditModule extends AbstractModule
     /**
      * @inheritdoc
      */
+    public function getIconIdentifier(): string
+    {
+        return 'actions-open';
+    }
+
+    /**
+     * @inheritdoc
+     */
     public function getLabel(): string
     {
-        return $this->extGetLL('edit');
+        $locallangFileAndPath = 'LLL:' . $this->extResources . '/Language/locallang_edit.xlf:module.label';
+        return $this->getLanguageService()->sL($locallangFileAndPath);
     }
 
     /**
      * Initialize the edit module
      * Includes the frontend edit initialization
      *
-     * @param ServerRequest $request
+     * @param ServerRequestInterface $request
      *
      * @todo move into fe_edit (including the module)
      */
-    public function initializeModule(ServerRequest $request): void
+    public function initializeModule(ServerRequestInterface $request): void
     {
         $extFeEditLoaded = ExtensionManagementUtility::isLoaded('feedit');
         $typoScriptFrontend = $this->getTypoScriptFrontendController();
-        $typoScriptFrontend->displayEditIcons = $this->getConfigurationOption('displayIcons');
-        $typoScriptFrontend->displayFieldEditIcons = $this->getConfigurationOption('displayFieldIcons');
+        $typoScriptFrontend->displayEditIcons = $this->configurationService->getConfigurationOption('edit', 'displayIcons');
+        $typoScriptFrontend->displayFieldEditIcons = $this->configurationService->getConfigurationOption('edit', 'displayFieldIcons');
 
         if (GeneralUtility::_GP('ADMCMD_editIcons')) {
             $typoScriptFrontend->displayFieldEditIcons = '1';
@@ -121,18 +130,10 @@ class EditModule extends AbstractModule
     }
 
     /**
-     * @inheritdoc
-     */
-    public function showFormSubmitButton(): bool
-    {
-        return true;
-    }
-
-    /**
      * @return array
      */
     public function getJavaScriptFiles(): array
     {
-        return ['EXT:adminpanel/Resources/Public/JavaScript/Modules/Edit/OpenBackendHandler.js'];
+        return ['EXT:adminpanel/Resources/Public/JavaScript/Modules/Edit.js'];
     }
 }
diff --git a/typo3/sysext/adminpanel/Classes/Modules/Info/GeneralInformation.php b/typo3/sysext/adminpanel/Classes/Modules/Info/GeneralInformation.php
new file mode 100644 (file)
index 0000000..bd8339b
--- /dev/null
@@ -0,0 +1,172 @@
+<?php
+declare(strict_types = 1);
+
+namespace TYPO3\CMS\Adminpanel\Modules\Info;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use TYPO3\CMS\Adminpanel\Modules\AbstractSubModule;
+use TYPO3\CMS\Core\Context\Context;
+use TYPO3\CMS\Core\Context\UserAspect;
+use TYPO3\CMS\Core\TimeTracker\TimeTracker;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Fluid\View\StandaloneView;
+use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
+
+/**
+ * General information module displaying info about the current
+ * request
+ */
+class GeneralInformation extends AbstractSubModule
+{
+    /**
+     * Creates the content for the "info" section ("module") of the Admin Panel
+     *
+     * @return string HTML content for the section. Consists of a string with table-rows with four columns.
+     * @see display()
+     */
+    public function getContent(): string
+    {
+        /** @var UserAspect $frontendUserAspect */
+        $frontendUserAspect = GeneralUtility::makeInstance(Context::class)->getAspect('frontend.user');
+        $view = GeneralUtility::makeInstance(StandaloneView::class);
+        $templateNameAndPath = 'EXT:adminpanel/Resources/Private/Templates/Modules/Info/General.html';
+        $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName($templateNameAndPath));
+        $view->setPartialRootPaths(['EXT:adminpanel/Resources/Private/Partials']);
+        $tsfe = $this->getTypoScriptFrontendController();
+
+        $view->assignMultiple(
+            [
+                'post' => $_POST,
+                'get' => $_GET,
+                'cookie' => $_COOKIE,
+                'server' => $_SERVER,
+                'info' => [
+                    'pageUid' => $tsfe->id,
+                    'pageType' => $tsfe->type,
+                    'groupList' => implode(',', $frontendUserAspect->getGroupIds()),
+                    'noCache' => $this->isNoCacheEnabled(),
+                    'countUserInt' => \count($tsfe->config['INTincScript'] ?? []),
+                    'totalParsetime' => $this->getTimeTracker()->getParseTime(),
+                    'feUser' => [
+                        'uid' => $tsfe->fe_user->user['uid'] ?? 0,
+                        'username' => $tsfe->fe_user->user['username'] ?? ''
+                    ],
+                    'imagesOnPage' => $this->collectImagesOnPage(),
+                    'documentSize' => $this->collectDocumentSize()
+                ]
+            ]
+        );
+
+        return $view->render();
+    }
+
+    /**
+     * Identifier for this Sub-module,
+     * for example "preview" or "cache"
+     *
+     * @return string
+     */
+    public function getIdentifier(): string
+    {
+        return 'info_general';
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function getLabel(): string
+    {
+        return $this->getLanguageService()->sL(
+            'LLL:EXT:adminpanel/Resources/Private/Language/locallang_info.xlf:sub.general.label'
+        );
+    }
+
+    /**
+     * Collects images from TypoScriptFrontendController and calculates the total size.
+     * Returns human readable image sizes for fluid template output
+     *
+     * @return array
+     */
+    protected function collectImagesOnPage(): array
+    {
+        $imagesOnPage = [
+            'files' => [],
+            'total' => 0,
+            'totalSize' => 0,
+            'totalSizeHuman' => GeneralUtility::formatSize(0)
+        ];
+
+        if ($this->isNoCacheEnabled() === false) {
+            return $imagesOnPage;
+        }
+
+        $count = 0;
+        $totalImageSize = 0;
+        if (!empty($this->getTypoScriptFrontendController()->imagesOnPage)) {
+            foreach ($this->getTypoScriptFrontendController()->imagesOnPage as $file) {
+                $fileSize = @filesize($file);
+                $imagesOnPage['files'][] = [
+                    'name' => $file,
+                    'size' => $fileSize,
+                    'sizeHuman' => GeneralUtility::formatSize($fileSize)
+                ];
+                $totalImageSize += $fileSize;
+                $count++;
+            }
+        }
+        $imagesOnPage['totalSize'] = GeneralUtility::formatSize($totalImageSize);
+        $imagesOnPage['total'] = $count;
+        return $imagesOnPage;
+    }
+
+    /**
+     * Gets the document size from the current page in a human readable format
+     *
+     * @return string
+     */
+    protected function collectDocumentSize(): string
+    {
+        $documentSize = 0;
+        if ($this->isNoCacheEnabled() === true) {
+            $documentSize = mb_strlen($this->getTypoScriptFrontendController()->content, 'UTF-8');
+        }
+
+        return GeneralUtility::formatSize($documentSize);
+    }
+
+    /**
+     * @return bool
+     */
+    protected function isNoCacheEnabled(): bool
+    {
+        return (bool)$this->getTypoScriptFrontendController()->no_cache;
+    }
+
+    /**
+     * @return TypoScriptFrontendController
+     */
+    protected function getTypoScriptFrontendController(): TypoScriptFrontendController
+    {
+        return $GLOBALS['TSFE'];
+    }
+
+    /**
+     * @return TimeTracker
+     */
+    protected function getTimeTracker(): TimeTracker
+    {
+        return GeneralUtility::makeInstance(TimeTracker::class);
+    }
+}
diff --git a/typo3/sysext/adminpanel/Classes/Modules/Info/PhpInformation.php b/typo3/sysext/adminpanel/Classes/Modules/Info/PhpInformation.php
new file mode 100644 (file)
index 0000000..a8b3af7
--- /dev/null
@@ -0,0 +1,71 @@
+<?php
+declare(strict_types = 1);
+
+namespace TYPO3\CMS\Adminpanel\Modules\Info;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use TYPO3\CMS\Adminpanel\Modules\AbstractSubModule;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Fluid\View\StandaloneView;
+
+/**
+ * PhpInformation admin panel sub module
+ */
+class PhpInformation extends AbstractSubModule
+{
+    /**
+     * @inheritdoc
+     */
+    public function getIdentifier(): string
+    {
+        return 'info_php';
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function getLabel(): string
+    {
+        return $this->getLanguageService()->sL(
+            'LLL:EXT:adminpanel/Resources/Private/Language/locallang_info.xlf:sub.php.label'
+        );
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function getContent(): string
+    {
+        $view = GeneralUtility::makeInstance(StandaloneView::class);
+        $templateNameAndPath = 'EXT:adminpanel/Resources/Private/Templates/Modules/Info/PhpInfo.html';
+        $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName($templateNameAndPath));
+        $view->setPartialRootPaths(['EXT:adminpanel/Resources/Private/Partials']);
+
+        $view->assignMultiple(
+            [
+                'general' => [
+                    'PHP_VERSION' => PHP_VERSION,
+                    'PHP_OS' => PHP_OS,
+                    'PHP_SAPI' => PHP_SAPI,
+                    'Peak Memory Usage' => memory_get_peak_usage(),
+                ],
+                'loadedExtensions' => implode(', ', get_loaded_extensions()),
+                'constants' => get_defined_constants(true),
+            ]
+        );
+
+        return $view->render();
+    }
+}
diff --git a/typo3/sysext/adminpanel/Classes/Modules/Info/RequestInformation.php b/typo3/sysext/adminpanel/Classes/Modules/Info/RequestInformation.php
new file mode 100644 (file)
index 0000000..cd2a46f
--- /dev/null
@@ -0,0 +1,68 @@
+<?php
+declare(strict_types = 1);
+
+namespace TYPO3\CMS\Adminpanel\Modules\Info;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use TYPO3\CMS\Adminpanel\Modules\AbstractSubModule;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Fluid\View\StandaloneView;
+
+/**
+ * RequestInformation submodule of the admin panel
+ */
+class RequestInformation extends AbstractSubModule
+{
+    /**
+     * @inheritdoc
+     */
+    public function getIdentifier(): string
+    {
+        return 'info-request';
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function getLabel(): string
+    {
+        return $this->getLanguageService()->sL(
+            'LLL:EXT:adminpanel/Resources/Private/Language/locallang_info.xlf:sub.request.label'
+        );
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function getContent(): string
+    {
+        $view = GeneralUtility::makeInstance(StandaloneView::class);
+        $templateNameAndPath = 'EXT:adminpanel/Resources/Private/Templates/Modules/Info/RequestInformation.html';
+        $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName($templateNameAndPath));
+        $view->setPartialRootPaths(['EXT:adminpanel/Resources/Private/Partials']);
+
+        $view->assignMultiple(
+            [
+                'post' => $_POST,
+                'get' => $_GET,
+                'cookie' => $_COOKIE,
+                'session' => $_SESSION,
+                'server' => $_SERVER,
+            ]
+        );
+
+        return $view->render();
+    }
+}
index c1e5448..eb833b8 100644 (file)
@@ -16,12 +16,8 @@ namespace TYPO3\CMS\Adminpanel\Modules;
  * The TYPO3 project - inspiring people to share!
  */
 
-use TYPO3\CMS\Core\Context\Context;
-use TYPO3\CMS\Core\Context\UserAspect;
 use TYPO3\CMS\Core\TimeTracker\TimeTracker;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
-use TYPO3\CMS\Fluid\View\StandaloneView;
-use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
 
 /**
  * Admin Panel Info Module
@@ -29,39 +25,11 @@ use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
 class InfoModule extends AbstractModule
 {
     /**
-     * Creates the content for the "info" section ("module") of the Admin Panel
-     *
-     * @return string HTML content for the section. Consists of a string with table-rows with four columns.
-     * @see display()
+     * @inheritdoc
      */
-    public function getContent(): string
+    public function getIconIdentifier(): string
     {
-        $view = GeneralUtility::makeInstance(StandaloneView::class);
-        $templateNameAndPath = $this->extResources . '/Templates/Modules/Info.html';
-        $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName($templateNameAndPath));
-        $view->setPartialRootPaths([$this->extResources . '/Partials']);
-        $tsfe = $this->getTypoScriptFrontendController();
-
-        /** @var UserAspect $frontendUserAspect */
-        $frontendUserAspect = GeneralUtility::makeInstance(Context::class)->getAspect('frontend.user');
-        $view->assignMultiple([
-            'info' => [
-                'pageUid' => $tsfe->id,
-                'pageType' => $tsfe->type,
-                'groupList' => implode(',', $frontendUserAspect->getGroupIds()),
-                'noCache' => $this->isNoCacheEnabled(),
-                'countUserInt' => \count($tsfe->config['INTincScript'] ?? []),
-                'totalParsetime' => $this->getTimeTracker()->getParseTime(),
-                'feUser' => [
-                    'uid' => $frontendUserAspect->get('id'),
-                    'username' => $frontendUserAspect->get('username')
-                ],
-                'imagesOnPage' => $this->collectImagesOnPage(),
-                'documentSize' => $this->collectDocumentSize()
-            ]
-        ]);
-
-        return $view->render();
+        return 'actions-document-info';
     }
 
     /**
@@ -77,16 +45,20 @@ class InfoModule extends AbstractModule
      */
     public function getLabel(): string
     {
-        $locallangFileAndPath = 'LLL:' . $this->extResources . '/Language/locallang_info.xlf:module.label';
-        return $this->getLanguageService()->sL($locallangFileAndPath);
+        return $this->getLanguageService()->sL(
+            'LLL:EXT:adminpanel/Resources/Private/Language/locallang_info.xlf:module.label'
+        );
     }
 
     /**
-     * @return TypoScriptFrontendController
+     * @inheritdoc
      */
-    protected function getTypoScriptFrontendController(): TypoScriptFrontendController
+    public function getShortInfo(): string
     {
-        return $GLOBALS['TSFE'];
+        $parseTime = $this->getTimeTracker()->getParseTime();
+        return sprintf($this->getLanguageService()->sL(
+            'LLL:EXT:adminpanel/Resources/Private/Language/locallang_info.xlf:module.shortinfo'
+        ), $parseTime);
     }
 
     /**
@@ -96,64 +68,4 @@ class InfoModule extends AbstractModule
     {
         return GeneralUtility::makeInstance(TimeTracker::class);
     }
-
-    /**
-     * Collects images from TypoScriptFrontendController and calculates the total size.
-     * Returns human readable image sizes for fluid template output
-     *
-     * @return array
-     */
-    protected function collectImagesOnPage(): array
-    {
-        $imagesOnPage = [
-            'files' => [],
-            'total' => 0,
-            'totalSize' => 0,
-            'totalSizeHuman' => GeneralUtility::formatSize(0)
-        ];
-
-        if ($this->isNoCacheEnabled() === false) {
-            return $imagesOnPage;
-        }
-
-        $count = 0;
-        $totalImageSize = 0;
-        if (!empty($this->getTypoScriptFrontendController()->imagesOnPage)) {
-            foreach ($this->getTypoScriptFrontendController()->imagesOnPage as $file) {
-                $fileSize = @filesize($file);
-                $imagesOnPage['files'][] = [
-                    'name' => $file,
-                    'size' => $fileSize,
-                    'sizeHuman' => GeneralUtility::formatSize($fileSize)
-                ];
-                $totalImageSize += $fileSize;
-                $count++;
-            }
-        }
-        $imagesOnPage['totalSize'] = GeneralUtility::formatSize($totalImageSize);
-        $imagesOnPage['total'] = $count;
-        return $imagesOnPage;
-    }
-
-    /**
-     * Gets the document size from the current page in a human readable format
-     * @return string
-     */
-    protected function collectDocumentSize(): string
-    {
-        $documentSize = 0;
-        if ($this->isNoCacheEnabled() === true) {
-            $documentSize = \mb_strlen($this->getTypoScriptFrontendController()->content, 'UTF-8');
-        }
-
-        return GeneralUtility::formatSize($documentSize);
-    }
-
-    /**
-     * @return bool
-     */
-    protected function isNoCacheEnabled(): bool
-    {
-        return (bool)$this->getTypoScriptFrontendController()->no_cache;
-    }
 }
index d228d71..30e75b3 100644 (file)
@@ -16,13 +16,13 @@ namespace TYPO3\CMS\Adminpanel\Modules;
  * The TYPO3 project - inspiring people to share!
  */
 
+use Psr\Http\Message\ServerRequestInterface;
 use TYPO3\CMS\Adminpanel\Repositories\FrontendGroupsRepository;
+use TYPO3\CMS\Core\Cache\CacheManager;
 use TYPO3\CMS\Core\Context\Context;
 use TYPO3\CMS\Core\Context\DateTimeAspect;
 use TYPO3\CMS\Core\Context\UserAspect;
 use TYPO3\CMS\Core\Context\VisibilityAspect;
-use TYPO3\CMS\Core\Http\ServerRequest;
-use TYPO3\CMS\Core\Type\Bitmask\Permission;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Fluid\View\StandaloneView;
 use TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication;
@@ -34,51 +34,18 @@ use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
 class PreviewModule extends AbstractModule
 {
     /**
-     * Force the preview panel to be opened
+     * module configuration, set on initialize
      *
-     * @var bool
+     * @var array
      */
-    protected $forceOpen = false;
+    protected $config;
 
     /**
      * @inheritdoc
      */
-    public function getAdditionalJavaScriptCode(): string
+    public function getIconIdentifier(): string
     {
-        return 'TSFEtypo3FormFieldSet("TSFE_ADMIN_PANEL[preview_simulateDate]", "datetime", "", 0, 0);';
-    }
-
-    /**
-     * Creates the content for the "preview" section ("module") of the Admin Panel
-     *
-     * @return string HTML content for the section. Consists of a string with table-rows with four columns.
-     * @see display()
-     * @throws \InvalidArgumentException
-     */
-    public function getContent(): string
-    {
-        $view = GeneralUtility::makeInstance(StandaloneView::class);
-        $templateNameAndPath = $this->extResources . '/Templates/Modules/Preview.html';
-        $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName($templateNameAndPath));
-        $view->setPartialRootPaths([$this->extResources . '/Partials']);
-
-        $frontendGroupsRepository = GeneralUtility::makeInstance(FrontendGroupsRepository::class);
-
-        $view->assignMultiple(
-            [
-                'show' => [
-                    'hiddenPages' => $this->getConfigurationOption('showHiddenPages'),
-                    'hiddenRecords' => $this->getConfigurationOption('showHiddenRecords'),
-                    'fluidDebug' => $this->getConfigurationOption('showFluidDebug'),
-                ],
-                'simulateDate' => $this->getConfigurationOption('simulateDate'),
-                'frontendUserGroups' => [
-                    'availableGroups' => $frontendGroupsRepository->getAvailableFrontendUserGroups(),
-                    'selected' => $this->getConfigurationOption('simulateUserGroup'),
-                ],
-            ]
-        );
-        return $view->render();
+        return 'actions-preview';
     }
 
     /**
@@ -94,70 +61,88 @@ class PreviewModule extends AbstractModule
      */
     public function getLabel(): string
     {
-        $locallangFileAndPath = 'LLL:' . $this->extResources . '/Language/locallang_preview.xlf:module.label';
-        return $this->getLanguageService()->sL($locallangFileAndPath);
+        return $this->getLanguageService()->sL(
+            'LLL:' . $this->extResources . '/Language/locallang_preview.xlf:module.label'
+        );
     }
 
     /**
-     * @param ServerRequest $request
+     * @inheritdoc
      */
-    public function initializeModule(ServerRequest $request): void
+    public function initializeModule(ServerRequestInterface $request): void
     {
-        $this->initializeFrontendPreview();
-        if (GeneralUtility::_GP('ADMCMD_simUser')) {
-            $this->getBackendUser()->uc['TSFE_adminConfig']['preview_simulateUserGroup'] = (int)GeneralUtility::_GP(
-                'ADMCMD_simUser'
-            );
-            $this->forceOpen = true;
-        }
-        if (GeneralUtility::_GP('ADMCMD_simTime')) {
-            $this->getBackendUser()->uc['TSFE_adminConfig']['preview_simulateDate'] = (int)GeneralUtility::_GP(
-                'ADMCMD_simTime'
-            );
-            $this->forceOpen = true;
-        }
+        $this->config = [
+            'showHiddenPages' => (bool)$this->getConfigOptionForModule('showHiddenPages'),
+            'simulateDate' => $this->getConfigOptionForModule('simulateDate'),
+            'showHiddenRecords' => (bool)$this->getConfigOptionForModule('showHiddenRecords'),
+            'simulateUserGroup' => $this->getConfigOptionForModule('simulateUserGroup'),
+            'showFluidDebug' => (bool)$this->getConfigOptionForModule('showFluidDebug'),
+        ];
+        $this->initializeFrontendPreview(
+            $this->config['showHiddenPages'],
+            $this->config['showHiddenRecords'],
+            $this->config['simulateDate'],
+            $this->config['simulateUserGroup']
+        );
     }
 
     /**
-     * Force module to be shown if either time or users/groups are simulated
-     *
-     * @return bool
+     * @inheritdoc
      */
-    public function isShown(): bool
+    public function getSettings(): string
     {
-        if ($this->forceOpen) {
-            return true;
-        }
-        return parent::isShown();
+        $view = GeneralUtility::makeInstance(StandaloneView::class);
+        $templateNameAndPath = $this->extResources . '/Templates/Modules/Settings/Preview.html';
+        $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName($templateNameAndPath));
+        $view->setPartialRootPaths([$this->extResources . '/Partials']);
+
+        $frontendGroupsRepository = GeneralUtility::makeInstance(FrontendGroupsRepository::class);
+
+        $view->assignMultiple(
+            [
+                'show' => [
+                    'pageId' => (int)$this->getTypoScriptFrontendController()->id,
+                    'hiddenPages' => $this->config['showHiddenPages'],
+                    'hiddenRecords' => $this->config['showHiddenRecords'],
+                    'fluidDebug' => $this->config['showFluidDebug'],
+                ],
+                'simulateDate' => $this->config['simulateDate'],
+                'frontendUserGroups' => [
+                    'availableGroups' => $frontendGroupsRepository->getAvailableFrontendUserGroups(),
+                    'selected' => $this->config['simulateUserGroup'],
+                ],
+            ]
+        );
+        return $view->render();
     }
 
     /**
      * Clear page cache if fluid debug output is enabled
      *
      * @param array $input
+     * @param ServerRequestInterface $request
+     * @throws \TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException
      */
-    public function onSubmit(array $input): void
+    public function onSubmit(array $input, ServerRequestInterface $request): void
     {
-        if ($input['preview_showFluidDebug'] ?? false) {
-            $theStartId = (int)$this->getTypoScriptFrontendController()->id;
-            $this->getTypoScriptFrontendController()
-                ->clearPageCacheContent_pidList(
-                    $this->getBackendUser()->extGetTreeList(
-                        $theStartId,
-                        0,
-                        0,
-                        $this->getBackendUser()->getPagePermsClause(Permission::PAGE_SHOW)
-                    ) . $theStartId
-                );
+        $activeConfiguration = (int)$this->getConfigOptionForModule('showFluidDebug');
+        if (isset($input['preview_showFluidDebug']) && (int)$input['preview_showFluidDebug'] !== $activeConfiguration) {
+            $pageId = (int)$request->getParsedBody()['TSFE_ADMIN_PANEL']['preview_clearCacheId'];
+            $cache = GeneralUtility::makeInstance(CacheManager::class)->getCache('cache_pages');
+            $cache->flushByTag('pageId_' . $pageId);
         }
     }
 
     /**
-     * @inheritdoc
+     * @param string $option
+     * @return string
      */
-    public function showFormSubmitButton(): bool
+    protected function getConfigOptionForModule(string $option): string
     {
-        return true;
+        return $this->configurationService->getConfigurationOption(
+            'preview',
+            $option
+        );
     }
 
     /**
@@ -171,25 +156,35 @@ class PreviewModule extends AbstractModule
     /**
      * Initialize frontend preview functionality incl.
      * simulation of users or time
+     *
+     * @param bool $showHiddenPages
+     * @param bool $showHiddenRecords
+     * @param string $simulateDate
+     * @param string $simulateUserGroup
      */
-    protected function initializeFrontendPreview()
-    {
+    protected function initializeFrontendPreview(
+        bool $showHiddenPages,
+        bool $showHiddenRecords,
+        string $simulateDate,
+        string $simulateUserGroup
+    ): void {
         $context = GeneralUtility::makeInstance(Context::class);
         $tsfe = $this->getTypoScriptFrontendController();
         $tsfe->clear_preview();
         $tsfe->fePreview = 1;
-        $showHiddenPage = (bool)$this->getConfigurationOption('showHiddenPages');
-        $showHiddenRecords = (bool)$this->getConfigurationOption('showHiddenRecords');
         // Simulate date
-        $simTime = $this->getConfigurationOption('simulateDate');
+        $simTime = null;
+        if ($simulateDate) {
+            $simTime = $this->parseDate($simulateDate);
+        }
         if ($simTime) {
             $GLOBALS['SIM_EXEC_TIME'] = $simTime;
             $GLOBALS['SIM_ACCESS_TIME'] = $simTime - $simTime % 60;
             $context->setAspect('date', GeneralUtility::makeInstance(DateTimeAspect::class, new \DateTimeImmutable('@' . $GLOBALS['SIM_EXEC_TIME'])));
         }
-        $context->setAspect('visibility', GeneralUtility::makeInstance(VisibilityAspect::class, $showHiddenPage, $showHiddenRecords));
+        $context->setAspect('visibility', GeneralUtility::makeInstance(VisibilityAspect::class, $showHiddenPages, $showHiddenRecords));
         // simulate user
-        $tsfe->simUserGroup = $this->getConfigurationOption('simulateUserGroup');
+        $tsfe->simUserGroup = $simulateUserGroup;
         if ($tsfe->simUserGroup) {
             if ($tsfe->fe_user->user) {
                 $tsfe->fe_user->user[$tsfe->fe_user->usergroup_column] = $tsfe->simUserGroup;
@@ -201,8 +196,40 @@ class PreviewModule extends AbstractModule
             }
             $context->setAspect('frontend.user', GeneralUtility::makeInstance(UserAspect::class, $tsfe->fe_user ?: null));
         }
-        if (!$tsfe->simUserGroup && !$simTime && !$showHiddenPage && !$showHiddenRecords) {
+        if (!$tsfe->simUserGroup && !$simTime && !$showHiddenPages && !$showHiddenRecords) {
             $tsfe->fePreview = 0;
         }
     }
+
+    /**
+     * @return array
+     */
+    public function getJavaScriptFiles(): array
+    {
+        return ['EXT:adminpanel/Resources/Public/JavaScript/Modules/Preview.js'];
+    }
+
+    /**
+     * @param string $simulateDate
+     * @return int
+     */
+    protected function parseDate(string $simulateDate): ?int
+    {
+        $date = false;
+        try {
+            $date = new \DateTime($simulateDate);
+        } catch (\Exception $e) {
+            if (is_numeric($simulateDate)) {
+                try {
+                    $date = new \DateTime('@' . $simulateDate);
+                } catch (\Exception $e) {
+                    $date = false;
+                }
+            }
+        }
+        if ($date !== false) {
+            $simTime = $date->getTimestamp();
+        }
+        return $simTime ?? null;
+    }
 }
diff --git a/typo3/sysext/adminpanel/Classes/Modules/TsDebug/TypoScriptWaterfall.php b/typo3/sysext/adminpanel/Classes/Modules/TsDebug/TypoScriptWaterfall.php
new file mode 100644 (file)
index 0000000..b4368ba
--- /dev/null
@@ -0,0 +1,185 @@
+<?php
+declare(strict_types = 1);
+
+namespace TYPO3\CMS\Adminpanel\Modules\TsDebug;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use Psr\Http\Message\ServerRequestInterface;
+use TYPO3\CMS\Adminpanel\Modules\AbstractSubModule;
+use TYPO3\CMS\Adminpanel\Service\ConfigurationService;
+use TYPO3\CMS\Backend\FrontendBackendUserAuthentication;
+use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
+use TYPO3\CMS\Core\TimeTracker\TimeTracker;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Fluid\View\StandaloneView;
+use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
+
+class TypoScriptWaterfall extends AbstractSubModule
+{
+    /**
+     * @var ConfigurationService
+     */
+    protected $configurationService;
+
+    public function __construct()
+    {
+        $this->configurationService = GeneralUtility::makeInstance(ConfigurationService::class);
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function getIdentifier(): string
+    {
+        return 'typoscript-waterfall';
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function getLabel(): string
+    {
+        return $this->getLanguageService()->sL(
+            'LLL:' . 'EXT:adminpanel/Resources/Private/Language/locallang_tsdebug.xlf:sub.waterfall.label'
+        );
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function initializeModule(ServerRequestInterface $request): void
+    {
+        $typoScriptFrontend = $this->getTypoScriptFrontendController();
+        $typoScriptFrontend->forceTemplateParsing = $this->getConfigurationOption(
+            'forceTemplateParsing'
+        );
+        if ($typoScriptFrontend->forceTemplateParsing) {
+            $typoScriptFrontend->set_no_cache('Admin Panel: Force template parsing', true);
+        }
+        $this->getTimeTracker()->LR = $this->getConfigurationOption('LR');
+    }
+
+    /**
+     * Creates the content for the "tsdebug" section ("module") of the Admin Panel
+     *
+     * @return string HTML
+     */
+    public function getContent(): string
+    {
+        $view = GeneralUtility::makeInstance(StandaloneView::class);
+        $templateNameAndPath = 'EXT:adminpanel/Resources/Private/Templates/Modules/TsDebug/TypoScript.html';
+        $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName($templateNameAndPath));
+        $view->setPartialRootPaths(['EXT:adminpanel/Resources/Private/Partials']);
+
+        $view->assignMultiple(
+            [
+                'tree' => (int)$this->getConfigurationOption('tree'),
+                'display' => [
+                    'times' => (int)$this->getConfigurationOption('displayTimes'),
+                    'messages' => (int)$this->getConfigurationOption('displayMessages'),
+                    'content' => (int)$this->getConfigurationOption('displayContent'),
+                ],
+                'trackContentRendering' => (int)$this->getConfigurationOption('LR'),
+                'forceTemplateParsing' => (int)$this->getConfigurationOption('forceTemplateParsing'),
+                'typoScriptLog' => $this->renderTypoScriptLog(),
+            ]
+        );
+
+        return $view->render();
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function getSettings(): string
+    {
+        $view = GeneralUtility::makeInstance(StandaloneView::class);
+        $templateNameAndPath = 'EXT:adminpanel/Resources/Private/Templates/Modules/TsDebug/TypoScriptSettings.html';
+        $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName($templateNameAndPath));
+        $view->setPartialRootPaths(['EXT:adminpanel/Resources/Private/Partials']);
+
+        $view->assignMultiple(
+            [
+                'tree' => (int)$this->getConfigurationOption('tree'),
+                'display' => [
+                    'times' => (int)$this->getConfigurationOption('displayTimes'),
+                    'messages' => (int)$this->getConfigurationOption('displayMessages'),
+                    'content' => (int)$this->getConfigurationOption('displayContent'),
+                ],
+                'trackContentRendering' => (int)$this->getConfigurationOption('LR'),
+                'forceTemplateParsing' => (int)$this->getConfigurationOption('forceTemplateParsing'),
+                'typoScriptLog' => $this->renderTypoScriptLog(),
+            ]
+        );
+
+        return $view->render();
+    }
+
+    /**
+     * Returns the current BE user.
+     *
+     * @return BackendUserAuthentication|FrontendBackendUserAuthentication
+     */
+    protected function getBackendUser(): BackendUserAuthentication
+    {
+        return $GLOBALS['BE_USER'];
+    }
+
+    /**
+     * @param string $option
+     * @return bool
+     */
+    protected function getConfigurationOption(string $option): bool
+    {
+        return (bool)$this->configurationService->getConfigurationOption('tsdebug', $option);
+    }
+
+    /**
+     * Renders the TypoScript log as string
+     *
+     * @return string
+     */
+    protected function renderTypoScriptLog(): string
+    {
+        $timeTracker = $this->getTimeTracker();
+        $timeTracker->printConf['flag_tree'] = $this->getConfigurationOption('tree');
+        $timeTracker->printConf['allTime'] = $this->getConfigurationOption(
+            'displayTimes'
+        );
+        $timeTracker->printConf['flag_messages'] = $this->getConfigurationOption(
+            'displayMessages'
+        );
+        $timeTracker->printConf['flag_content'] = $this->getConfigurationOption(
+            'displayContent'
+        );
+        return $timeTracker->printTSlog();
+    }
+
+    /**
+     * @return TimeTracker
+     */
+    protected function getTimeTracker(): TimeTracker
+    {
+        return GeneralUtility::makeInstance(TimeTracker::class);
+    }
+
+    /**
+     * @return TypoScriptFrontendController
+     */
+    protected function getTypoScriptFrontendController(): TypoScriptFrontendController
+    {
+        return $GLOBALS['TSFE'];
+    }
+}
index c888021..5990668 100644 (file)
@@ -16,11 +16,8 @@ namespace TYPO3\CMS\Adminpanel\Modules;
  * The TYPO3 project - inspiring people to share!
  */
 
-use TYPO3\CMS\Core\Http\ServerRequest;
 use TYPO3\CMS\Core\TimeTracker\TimeTracker;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
-use TYPO3\CMS\Fluid\View\StandaloneView;
-use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
 
 /**
  * Admin Panel TypoScript Debug Module
@@ -28,35 +25,6 @@ use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
 class TsDebugModule extends AbstractModule
 {
     /**
-     * Creates the content for the "tsdebug" section ("module") of the Admin Panel
-     *
-     * @return string HTML content for the section. Consists of a string with table-rows with four columns.
-     */
-    public function getContent(): string
-    {
-        $view = GeneralUtility::makeInstance(StandaloneView::class);
-        $templateNameAndPath = $this->extResources . '/Templates/Modules/TsDebug.html';
-        $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName($templateNameAndPath));
-        $view->setPartialRootPaths([$this->extResources . '/Partials']);
-
-        $tsfeAdminConfig = $this->getBackendUser()->uc['TSFE_adminConfig'];
-        $view->assignMultiple([
-            'isEnabled' => (int)$tsfeAdminConfig['display_tsdebug'],
-            'tree' => (int)$tsfeAdminConfig['tsdebug_tree'],
-            'display' => [
-                'times' => (int)$tsfeAdminConfig['tsdebug_displayTimes'],
-                'messages' => (int)$tsfeAdminConfig['tsdebug_displayMessages'],
-                'content' => (int)$tsfeAdminConfig['tsdebug_displayContent'],
-            ],
-            'trackContentRendering' => (int)$tsfeAdminConfig['tsdebug_LR'],
-            'forceTemplateParsing' => (int)$tsfeAdminConfig['tsdebug_forceTemplateParsing'],
-            'typoScriptLog' => $this->renderTypoScriptLog()
-        ]);
-
-        return $view->render();
-    }
-
-    /**
      * @inheritdoc
      */
     public function getIdentifier(): string
@@ -67,31 +35,33 @@ class TsDebugModule extends AbstractModule
     /**
      * @inheritdoc
      */
-    public function getLabel(): string
+    public function getIconIdentifier(): string
     {
-        $locallangFileAndPath = 'LLL:' . $this->extResources . '/Language/locallang_tsdebug.xlf:module.label';
-        return $this->getLanguageService()->sL($locallangFileAndPath);
+        return 'mimetypes-x-content-template-static';
     }
 
     /**
      * @inheritdoc
      */
-    public function initializeModule(ServerRequest $request): void
+    public function getLabel(): string
     {
-        $typoScriptFrontend = $this->getTypoScriptFrontendController();
-        $typoScriptFrontend->forceTemplateParsing = (bool)$this->getConfigurationOption('forceTemplateParsing');
-        if ($typoScriptFrontend->forceTemplateParsing) {
-            $typoScriptFrontend->set_no_cache('Admin Panel: Force template parsing', true);
-        }
-        $this->getTimeTracker()->LR = (bool)$this->getConfigurationOption('LR');
+        return $this->getLanguageService()->sL(
+            'LLL:EXT:adminpanel/Resources/Private/Language/locallang_tsdebug.xlf:module.label'
+        );
     }
 
     /**
      * @inheritdoc
      */
-    public function showFormSubmitButton(): bool
+    public function getShortInfo(): string
     {
-        return true;
+        $messageCount = 0;
+        foreach ($this->getTimeTracker()->tsStackLog as $log) {
+            $messageCount += count($log['message'] ?? []);
+        }
+        return sprintf($this->getLanguageService()->sL(
+            'LLL:EXT:adminpanel/Resources/Private/Language/locallang_tsdebug.xlf:module.shortinfo'
+        ), $messageCount);
     }
 
     /**
@@ -103,25 +73,10 @@ class TsDebugModule extends AbstractModule
     }
 
     /**
-     * @return TypoScriptFrontendController
-     */
-    protected function getTypoScriptFrontendController(): TypoScriptFrontendController
-    {
-        return $GLOBALS['TSFE'];
-    }
-
-    /**
-     * Renders the TypoScript log as string
-     *
-     * @return string
+     * @return array
      */
-    private function renderTypoScriptLog(): string
+    public function getJavaScriptFiles(): array
     {
-        $timeTracker = $this->getTimeTracker();
-        $timeTracker->printConf['flag_tree'] = $this->getConfigurationOption('tree');
-        $timeTracker->printConf['allTime'] = $this->getConfigurationOption('displayTimes');
-        $timeTracker->printConf['flag_messages'] = $this->getConfigurationOption('displayMessages');
-        $timeTracker->printConf['flag_content'] = $this->getConfigurationOption('displayContent');
-        return $timeTracker->printTSlog();
+        return ['EXT:adminpanel/Resources/Public/JavaScript/Modules/TsDebug.js'];
     }
 }
diff --git a/typo3/sysext/adminpanel/Classes/Service/ConfigurationService.php b/typo3/sysext/adminpanel/Classes/Service/ConfigurationService.php
new file mode 100644 (file)
index 0000000..add0623
--- /dev/null
@@ -0,0 +1,116 @@
+<?php
+declare(strict_types = 1);
+
+namespace TYPO3\CMS\Adminpanel\Service;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use Psr\Http\Message\ServerRequestInterface;
+use TYPO3\CMS\Adminpanel\Modules\AdminPanelModuleInterface;
+use TYPO3\CMS\Backend\FrontendBackendUserAuthentication;
+use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
+use TYPO3\CMS\Core\Cache\CacheManager;
+use TYPO3\CMS\Core\SingletonInterface;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+
+class ConfigurationService implements SingletonInterface
+{
+    /**
+     * @var array
+     */
+    protected $mainConfiguration;
+
+    public function __construct()
+    {
+        $this->mainConfiguration = $this->getBackendUser()->getTSConfig('admPanel')['properties'];
+    }
+
+    /**
+     * Get MainConfiguration (User TSConfig admPanel)
+     *
+     * @return array
+     */
+    public function getMainConfiguration(): array
+    {
+        return $this->mainConfiguration;
+    }
+
+    /**
+     * Helper method to return configuration options
+     * Checks User TSConfig overrides and current backend user session
+     *
+     * @param string $identifier
+     * @param string $option
+     * @return string
+     */
+    public function getConfigurationOption(string $identifier, string $option): string
+    {
+        $beUser = $this->getBackendUser();
+
+        if ($option && isset($this->mainConfiguration['override.'][$identifier . '.'][$option])) {
+            $returnValue = $this->mainConfiguration['override.'][$identifier . '.'][$option];
+        } else {
+            $returnValue = $beUser->uc['TSFE_adminConfig'][$identifier . '_' . $option] ?? '';
+        }
+
+        return (string)$returnValue;
+    }
+
+    /**
+     * Save admin panel configuration to backend user UC
+     * triggers onSubmit method of modules to enable each module
+     * to enhance the save action
+     *
+     * @param AdminPanelModuleInterface[] $modules
+     * @param ServerRequestInterface $request
+     * @throws \TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException
+     */
+    public function saveConfiguration(array $modules, ServerRequestInterface $request): void
+    {
+        $configurationToSave = $request->getParsedBody()['TSFE_ADMIN_PANEL'] ?? [];
+        $beUser = $this->getBackendUser();
+
+        // Trigger onSubmit
+        foreach ($modules as $module) {
+            if ($module->isEnabled()) {
+                $module->onSubmit($configurationToSave, $request);
+                foreach ($module->getSubModules() as $subModule) {
+                    $subModule->onSubmit($configurationToSave, $request);
+                }
+            }
+        }
+        // Settings
+        $beUser->uc['TSFE_adminConfig'] = array_merge(
+            !is_array($beUser->uc['TSFE_adminConfig']) ? [] : $beUser->uc['TSFE_adminConfig'],
+            $configurationToSave
+        );
+        unset($beUser->uc['TSFE_adminConfig']['action']);
+        // Saving
+        $beUser->writeUC();
+        // Flush fluid template cache
+        $cacheManager = GeneralUtility::makeInstance(CacheManager::class);
+        $cacheManager->setCacheConfigurations($GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']);
+        $cacheManager->getCache('fluid_template')->flush();
+    }
+
+    /**
+     * Returns the current BE user.
+     *
+     * @return BackendUserAuthentication|FrontendBackendUserAuthentication
+     */
+    protected function getBackendUser(): BackendUserAuthentication
+    {
+        return $GLOBALS['BE_USER'];
+    }
+}
index 3b2ddb4..5571452 100644 (file)
@@ -17,6 +17,7 @@ namespace TYPO3\CMS\Adminpanel\Service;
  */
 
 use TYPO3\CMS\Adminpanel\Modules\AdminPanelModuleInterface;
+use TYPO3\CMS\Adminpanel\Modules\AdminPanelSubModuleInterface;
 use TYPO3\CMS\Core\Service\DependencyOrderingService;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 
@@ -31,12 +32,13 @@ class ModuleLoader
     /**
      * Validates, sorts and initiates the registered modules
      *
+     * @param array $modules
+     * @param string $type
+     * @return AdminPanelModuleInterface[]|AdminPanelSubModuleInterface[]
      * @throws \RuntimeException
-     * @return AdminPanelModuleInterface[]
      */
-    public function getModulesFromConfiguration(): array
+    public function validateSortAndInitializeModules(array $modules, string $type = 'main'): array
     {
-        $modules = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules'] ?? [];
         if (empty($modules)) {
             return [];
         }
@@ -52,8 +54,9 @@ class ModuleLoader
                 !class_exists($configuration['module']) ||
                 !is_subclass_of(
                     $configuration['module'],
-                    AdminPanelModuleInterface::class
-                )) {
+                    ($type === 'main' ? AdminPanelModuleInterface::class : AdminPanelSubModuleInterface::class)
+                )
+            ) {
                 throw new \RuntimeException(
                     'The module "' .
                     $identifier .
@@ -69,11 +72,24 @@ class ModuleLoader
             $modules
         );
 
-        $finalModulesArr = [];
+        $moduleInstances = [];
         foreach ($orderedModules as $module) {
-            $finalModulesArr[] = GeneralUtility::makeInstance($module['module']);
+            $module = GeneralUtility::makeInstance($module['module']);
+            if ($module instanceof AdminPanelSubModuleInterface || ($module instanceof AdminPanelModuleInterface && $module->isEnabled())) {
+                $moduleInstances[] = $module;
+            }
         }
+        return $moduleInstances;
+    }
 
-        return $finalModulesArr;
+    /**
+     * Validates, sorts and initializes sub-modules
+     *
+     * @param array $modules
+     * @return AdminPanelSubModuleInterface[]
+     */
+    public function validateSortAndInitializeSubModules(array $modules): array
+    {
+        return $this->validateSortAndInitializeModules($modules, 'sub');
     }
 }
index f377574..4d31d6d 100644 (file)
@@ -17,9 +17,7 @@ namespace TYPO3\CMS\Adminpanel\View;
 
 use TYPO3\CMS\Adminpanel\Modules\AdminPanelModuleInterface;
 use TYPO3\CMS\Adminpanel\Service\EditToolbarService;
-use TYPO3\CMS\Backend\Routing\UriBuilder;
-use TYPO3\CMS\Core\Imaging\Icon;
-use TYPO3\CMS\Core\Imaging\IconFactory;
+use TYPO3\CMS\Core\Cache\CacheManager;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\PathUtility;
 
@@ -50,11 +48,6 @@ class AdminPanelView
     protected $extJSCODE = '';
 
     /**
-     * @var IconFactory
-     */
-    protected $iconFactory;
-
-    /**
      * Array of adminPanel modules
      *
      * @var AdminPanelModuleInterface[]
@@ -67,18 +60,11 @@ class AdminPanelView
     protected $configuration;
 
     /**
-     * Constructor
-     */
-    public function __construct()
-    {
-        $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
-    }
-
-    /**
      * Setter for injecting new-style modules
      *
      * @see \TYPO3\CMS\Adminpanel\Controller\MainController::render()
      * @param array $modules
+     * @internal
      */
     public function setModules(array $modules): void
     {
@@ -86,74 +72,61 @@ class AdminPanelView
     }
 
     /**
-     * Returns a link tag with the admin panel stylesheet
-     * defined using TBE_STYLES
+     * Returns true if admin panel was activated
+     * (switched "on" via GUI)
      *
-     * @return string
+     * @return bool
      */
-    protected function getAdminPanelStylesheet(): string
+    protected function isAdminPanelActivated(): bool
     {
-        $result = '';
-        if (!empty($GLOBALS['TBE_STYLES']['stylesheets']['admPanel'])) {
-            $stylesheet = GeneralUtility::locationHeaderUrl($GLOBALS['TBE_STYLES']['stylesheets']['admPanel']);
-            $result = '<link rel="stylesheet" type="text/css" href="' . htmlspecialchars($stylesheet) . '" />';
-        }
-        return $result;
+        return $this->getBackendUser()->uc['TSFE_adminConfig']['display_top'] ?? false;
     }
 
     /**
-     * Render a single module with header panel
+     * Returns LanguageService
      *
-     * @param \TYPO3\CMS\Adminpanel\Modules\AdminPanelModuleInterface $module
-     * @return string
+     * @return \TYPO3\CMS\Core\Localization\LanguageService
      */
-    protected function getModule(AdminPanelModuleInterface $module): string
+    protected function getLanguageService()
     {
-        $output = [];
-
-        if ($module->isEnabled()) {
-            $output[] = '<div class="typo3-adminPanel-section typo3-adminPanel-section-' .
-                        ($module->isOpen() ? 'open' : 'closed') .
-                        '">';
-            $output[] = '  <div class="typo3-adminPanel-section-title">';
-            $output[] = '    ' . $this->getSectionOpenerLink($module);
-            $output[] = '  </div>';
-            if ($module->isOpen()) {
-                $output[] = '<div class="typo3-adminPanel-section-body">';
-                $output[] = '  ' . $module->getContent();
-                $output[] = '</div>';
-            }
-            $output[] = '</div>';
-        }
+        return $GLOBALS['LANG'];
+    }
 
-        foreach ($module->getJavaScriptFiles() as $javaScriptFile) {
-            $output[] =
-                '<script src="' .
-                PathUtility::getAbsoluteWebPath(GeneralUtility::getFileAbsFileName($javaScriptFile)) .
-                '"></script>';
-        }
+    /**
+     * Returns the current BE user.
+     *
+     * @return \TYPO3\CMS\Backend\FrontendBackendUserAuthentication
+     */
+    protected function getBackendUser()
+    {
+        return $GLOBALS['BE_USER'];
+    }
 
-        return implode('', $output);
+    /**
+     * @return \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController
+     */
+    protected function getTypoScriptFrontendController()
+    {
+        return $GLOBALS['TSFE'];
     }
 
+    /*****************************************************
+     * Admin Panel: Deprecated API
+     ****************************************************/
+
     /**
-     * Creates and returns the HTML code for the Admin Panel in the TSFE frontend.
+     * Backwards compatibility method ensuring hook still gets the same content as before
      *
+     * @deprecated since TYPO3 v9 - remove when hook can be removed
+     * @internal
+     * @return string
      * @throws \UnexpectedValueException
-     * @return string HTML for the Admin Panel
      */
-    public function display()
+    public function callDeprecatedHookObject(): string
     {
-        $this->getLanguageService()->includeLLFile('EXT:core/Resources/Private/Language/locallang_tsfe.xlf');
-
         $moduleContent = '';
-
         if ($this->isAdminPanelActivated()) {
             foreach ($this->modules as $module) {
-                if ($module->isOpen()) {
-                    $this->extNeedUpdate = !$this->extNeedUpdate ? $module->showFormSubmitButton() : true;
-                    $this->extJSCODE .= $module->getAdditionalJavaScriptCode();
-                }
                 $moduleContent .= $this->getModule($module);
             }
 
@@ -183,144 +156,39 @@ class AdminPanelView
                 }
             }
         }
-
-        $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
-        $toggleActiveUrl = $uriBuilder->buildUriFromRoute('ajax_adminPanel_toggle');
-        $saveFormUrl = $uriBuilder->buildUriFromRoute('ajax_adminPanel_saveForm');
-
-        $output = [];
-        $output[] = '<!-- TYPO3 Admin panel start -->';
-        $output[] = '<a id="TSFE_ADMIN_PANEL"></a>';
-        $output[] = '<div data-typo3-role="typo3-adminPanel"><form id="TSFE_ADMIN_PANEL_FORM" name="TSFE_ADMIN_PANEL_FORM" style="display: none;" action="' . htmlspecialchars(GeneralUtility::getIndpEnv('TYPO3_REQUEST_SCRIPT')) . '#TSFE_ADMIN_PANEL" method="get" onsubmit="document.forms.TSFE_ADMIN_PANEL_FORM[\'TSFE_ADMIN_PANEL[DUMMY]\'].value=Math.random().toString().substring(2,8)">';
-        if (!GeneralUtility::_GET('id')) {
-            $output[] = '<input type="hidden" name="id" value="' . $this->getTypoScriptFrontendController()->id . '" />';
-        }
-        // The dummy field is needed for Firefox: to force a page reload on submit
-        // which must change the form value with JavaScript (see "onsubmit" attribute of the "form" element")
-        $output[] = '  <input type="hidden" name="TSFE_ADMIN_PANEL[DUMMY]" value="" />';
-        foreach (GeneralUtility::_GET() as $key => $value) {
-            if ($key !== 'TSFE_ADMIN_PANEL') {
-                if (is_array($value)) {
-                    $output[] = $this->getHiddenFields($key, $value);
-                } else {
-                    $output[] = '<input type="hidden" name="' . htmlspecialchars($key) . '" value="' . htmlspecialchars($value) . '" />';
-                }
-            }
-        }
-        $output[] = '  <input id="typo3AdminPanelCollapse" type="checkbox" value="1" />';
-        $output[] = '  <div class="typo3-adminPanel typo3-adminPanel-state-' .
-                    ($this->isAdminPanelActivated() ? 'open' : 'closed') .
-                    '">';
-        $output[] = '    <div class="typo3-adminPanel-header">';
-        $output[] = '      <span class="typo3-adminPanel-header-title">' . $this->extGetLL('adminPanelTitle') . '</span>';
-        $output[] = '      <span class="typo3-adminPanel-header-user">' . htmlspecialchars($this->getBackendUser()->user['username']) . '</span>';
-        $output[] = '      <label for="typo3AdminPanelEnable" data-typo3-role="typo3-adminPanel-trigger" data-typo3-ajax-url="' .
-                    $toggleActiveUrl .
-                    '" class="typo3-adminPanel-header-enable">';
-        if ($this->isAdminPanelActivated()) {
-            $output[] = '        <span class="typo3-adminPanel-header-enable-enabled">';
-            $output[] = '          ' . $this->iconFactory->getIcon('actions-edit-hide', Icon::SIZE_SMALL)->render('inline');
-            $output[] = '        </span>';
-        } else {
-            $output[] = '        <span class="typo3-adminPanel-header-enable-disabled">';
-            $output[] = '          ' . $this->iconFactory->getIcon('actions-edit-unhide', Icon::SIZE_SMALL)->render('inline');
-            $output[] = '        </span>';
-        }
-        $output[] = '      </label>';
-        $output[] = '      <label for="typo3AdminPanelCollapse" class="typo3-adminPanel-header-collapse">';
-        $output[] = '        <span class="typo3-adminPanel-header-collapse-enabled">';
-        $output[] = '          ' . $this->iconFactory->getIcon('actions-view-list-collapse', Icon::SIZE_SMALL)->render('inline');
-        $output[] = '        </span>';
-        $output[] = '        <span class="typo3-adminPanel-header-collapse-disabled">';
-        $output[] = '          ' . $this->iconFactory->getIcon('actions-view-list-expand', Icon::SIZE_SMALL)->render('inline');
-        $output[] = '        </span>';
-        $output[] = '      </label>';
-        $output[] = '    </div>';
-        if ($moduleContent && $this->extNeedUpdate) {
-            $output[] = '<div class="typo3-adminPanel-actions">';
-            $output[] = '  <button data-typo3-role="typo3-adminPanel-saveButton" data-typo3-ajax-url="' .
-                        $saveFormUrl .
-                        '" class="typo3-adminPanel-btn typo3-adminPanel-btn-dark">' . $this->extGetLL('update') . '</button>';
-            $output[] = '</div>';
-        }
-        $output[] = '    <div class="typo3-adminPanel-body">';
-        $output[] = '      ' . $moduleContent;
-        $output[] = '    </div>';
-        $output[] = '  </div>';
-        $output[] = '</form></div>';
-        if ($this->getBackendUser()->uc['TSFE_adminConfig']['display_top']) {
-            $evalFieldJavaScriptFile = GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Public/JavaScript/jsfunc.evalfield.js');
-            $output[] = '<script type="text/javascript" src="' . htmlspecialchars(PathUtility::getAbsoluteWebPath($evalFieldJavaScriptFile)) . '"></script>';
-            $output[] = '<script type="text/javascript">/*<![CDATA[*/' . GeneralUtility::minifyJavaScript('
-                               var evalFunc = new evalFunc();
-                                       // TSFEtypo3FormFieldSet()
-                               function TSFEtypo3FormFieldSet(theField, evallist, is_in, checkbox, checkboxValue) {    //
-                                       var theFObj = new evalFunc_dummy (evallist,is_in, checkbox, checkboxValue);
-                                       var theValue = document.TSFE_ADMIN_PANEL_FORM[theField].value;
-                                       if (checkbox && theValue==checkboxValue) {
-                                               document.TSFE_ADMIN_PANEL_FORM[theField+"_hr"].value="";
-                                               alert(theField);
-                                               document.TSFE_ADMIN_PANEL_FORM[theField+"_cb"].checked = "";
-                                       } else {
-                                               document.TSFE_ADMIN_PANEL_FORM[theField+"_hr"].value = evalFunc.outputObjValue(theFObj, theValue);
-                                               if (document.TSFE_ADMIN_PANEL_FORM[theField+"_cb"]) {
-                                                       document.TSFE_ADMIN_PANEL_FORM[theField+"_cb"].checked = "on";
-                                               }
-                                       }
-                               }
-                                       // TSFEtypo3FormFieldGet()
-                               function TSFEtypo3FormFieldGet(theField, evallist, is_in, checkbox, checkboxValue, checkbox_off) {      //
-                                       var theFObj = new evalFunc_dummy (evallist,is_in, checkbox, checkboxValue);
-                                       if (checkbox_off) {
-                                               document.TSFE_ADMIN_PANEL_FORM[theField].value=checkboxValue;
-                                       }else{
-                                               document.TSFE_ADMIN_PANEL_FORM[theField].value = evalFunc.evalObjValue(theFObj, document.TSFE_ADMIN_PANEL_FORM[theField+"_hr"].value);
-                                       }
-                                       TSFEtypo3FormFieldSet(theField, evallist, is_in, checkbox, checkboxValue);
-                               }') . '/*]]>*/</script>';
-            $output[] = '<script language="javascript" type="text/javascript">' . $this->extJSCODE . '</script>';
-        }
-        $cssFileLocation = GeneralUtility::getFileAbsFileName('EXT:adminpanel/Resources/Public/Css/adminpanel.css');
-        $jsFileLocation = GeneralUtility::getFileAbsFileName('EXT:adminpanel/Resources/Public/JavaScript/AdminPanel.js');
-        $output[] = '<link type="text/css" rel="stylesheet" href="' . htmlspecialchars(PathUtility::getAbsoluteWebPath($cssFileLocation)) . '" media="all" />';
-        $output[] = '<script type="text/javascript" src="' . htmlspecialchars(PathUtility::getAbsoluteWebPath($jsFileLocation)) . '"></script>';
-        $output[] = $this->getAdminPanelStylesheet();
-        $output[] = '<!-- TYPO3 admin panel end -->';
-
-        return implode('', $output);
+        return $moduleContent;
     }
 
     /**
-     * Fetches recursively all GET parameters as hidden fields.
-     * Called from display()
+     * Render a single module with header panel
      *
-     * @param string $key Current key
-     * @param array $val Current value
-     * @return string Hidden fields HTML-code
-     * @see display()
+     * @deprecated Since TYPO3 v9 - only used in deprecated hook call (which triggers the corresponding deprecation error)
+     * @param AdminPanelModuleInterface $module
+     * @return string
      */
-    protected function getHiddenFields($key, array $val)
+    protected function getModule(AdminPanelModuleInterface $module): string
     {
-        $out = '';
-        foreach ($val as $k => $v) {
-            if (is_array($v)) {
-                $out .= $this->getHiddenFields($key . '[' . $k . ']', $v);
-            } else {
-                $out .= '<input type="hidden" name="' . htmlspecialchars($key) . '[' . htmlspecialchars($k) . ']" value="' . htmlspecialchars($v) . '">' . LF;
-            }
+        $output = [];
+
+        if ($module->isEnabled()) {
+            $output[] = '<div class="typo3-adminPanel-section typo3-adminPanel-section-open">';
+            $output[] = '  <div class="typo3-adminPanel-section-title">';
+            $output[] = '    ' . $this->getSectionOpenerLink($module);
+            $output[] = '  </div>';
+            $output[] = '<div class="typo3-adminPanel-section-body">';
+            $output[] = '  ' . $module->getContent();
+            $output[] = '</div>';
+            $output[] = '</div>';
         }
-        return $out;
-    }
 
-    /**
-     * Returns true if admin panel was activated
-     * (switched "on" via GUI)
-     *
-     * @return bool
-     */
-    protected function isAdminPanelActivated(): bool
-    {
-        return $this->getBackendUser()->uc['TSFE_adminConfig']['display_top'] ?? false;
+        foreach ($module->getJavaScriptFiles() as $javaScriptFile) {
+            $output[] =
+                '<script src="' .
+                PathUtility::getAbsoluteWebPath(GeneralUtility::getFileAbsFileName($javaScriptFile)) .
+                '"></script>';
+        }
+
+        return implode('', $output);
     }
 
     /*****************************************************
@@ -330,6 +198,7 @@ class AdminPanelView
     /**
      * Wraps a string in a link which will open/close a certain part of the Admin Panel
      *
+     * @deprecated Since TYPO3 v9 - only used in deprecated hook call (which triggers the corresponding deprecation error)
      * @param AdminPanelModuleInterface $module
      * @return string
      */
@@ -350,7 +219,7 @@ class AdminPanelView
         $output[] = '<input type="hidden" name="TSFE_ADMIN_PANEL[display_' .
                     $identifier .
                     ']" value="' .
-                    (int)$module->isOpen() .
+                    1 .
                     '" />';
 
         return implode('', $output);
@@ -359,12 +228,16 @@ class AdminPanelView
     /**
      * Creates the tool bar links for the "edit" section of the Admin Panel.
      *
+     * @deprecated Since TYPO3 v9 - use EditToolbarService instead or create buttons via fluid
      * @deprecated
      * @return string A string containing images wrapped in <a>-tags linking them to proper functions.
      */
-    public function ext_makeToolBar()
+    public function ext_makeToolBar(): string
     {
-        trigger_error('', E_USER_DEPRECATED);
+        trigger_error(
+            'Deprecated since TYPO3 v9, use fluid and backend uri builder to create a toolbar',
+            \E_USER_DEPRECATED
+        );
         $editToolbarService = GeneralUtility::makeInstance(EditToolbarService::class);
         return $editToolbarService->createToolbar();
     }
@@ -372,8 +245,9 @@ class AdminPanelView
     /**
      * Translate given key
      *
-     * @param string $key Key for a label in the $LOCAL_LANG array of "sysext/core/Resources/Private/Language/locallang_tsfe.xlf
+     * @param string $key Key for a label in the $LOCAL_LANG array of "sysext/lang/Resources/Private/Language/locallang_tsfe.xlf
      * @param bool $convertWithHtmlspecialchars If TRUE the language-label will be sent through htmlspecialchars
+     * @deprecated Since TYPO3 v9 - only used in deprecated methods
      * @return string The value for the $key
      */
     protected function extGetLL($key, $convertWithHtmlspecialchars = true)
@@ -386,38 +260,6 @@ class AdminPanelView
     }
 
     /**
-     * Returns LanguageService
-     *
-     * @return \TYPO3\CMS\Core\Localization\LanguageService
-     */
-    protected function getLanguageService()
-    {
-        return $GLOBALS['LANG'];
-    }
-
-    /**
-     * Returns the current BE user.
-     *
-     * @return \TYPO3\CMS\Backend\FrontendBackendUserAuthentication
-     */
-    protected function getBackendUser()
-    {
-        return $GLOBALS['BE_USER'];
-    }
-
-    /**
-     * @return \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController
-     */
-    protected function getTypoScriptFrontendController()
-    {
-        return $GLOBALS['TSFE'];
-    }
-
-    /*****************************************************
-     * Admin Panel: Deprecated API
-     ****************************************************/
-
-    /**
      * Add an additional stylesheet
      *
      * @return string
@@ -429,18 +271,28 @@ class AdminPanelView
             'Deprecated since TYPO3 v9 - implement AdminPanelModules via the new API (see AdminPanelModuleInterface)',
             E_USER_DEPRECATED
         );
-        return $this->getAdminPanelStylesheet();
+        $result = '';
+        if (!empty($GLOBALS['TBE_STYLES']['stylesheets']['admPanel'])) {
+            $stylesheet = GeneralUtility::locationHeaderUrl($GLOBALS['TBE_STYLES']['stylesheets']['admPanel']);
+            $result = '<link rel="stylesheet" type="text/css" href="' .
+                      htmlspecialchars($stylesheet, ENT_QUOTES | ENT_HTML5) . '" />';
+        }
+        return $result;
     }
 
     /**
      * Checks if an Admin Panel section ("module") is available for the user. If so, TRUE is returned.
      *
      * @param string $key The module key, eg. "edit", "preview", "info" etc.
-     * @deprecated but still called in FrontendBackendUserAuthentication (will be refactored in a separate step)
+     * @deprecated
      * @return bool
      */
     public function isAdminModuleEnabled($key)
     {
+        trigger_error(
+            'Deprecated since TYPO3 v9 - implement AdminPanelModules via the new API (see AdminPanelModuleInterface)',
+            E_USER_DEPRECATED
+        );
         $result = false;
         // Returns TRUE if the module checked is "preview" and the forcePreview flag is set.
         if ($key === 'preview' && $this->ext_forcePreview) {
@@ -464,7 +316,29 @@ class AdminPanelView
             'Deprecated since TYPO3 v9 - implement AdminPanelModules via the new API (see AdminPanelModuleInterface)',
             E_USER_DEPRECATED
         );
-        $this->saveConfiguration();
+        $input = GeneralUtility::_GP('TSFE_ADMIN_PANEL');
+        $beUser = $this->getBackendUser();
+        if (is_array($input)) {
+            // Setting
+            $beUser->uc['TSFE_adminConfig'] = array_merge(
+                !is_array($beUser->uc['TSFE_adminConfig']) ? [] : $beUser->uc['TSFE_adminConfig'],
+                $input
+            );
+            unset($beUser->uc['TSFE_adminConfig']['action']);
+
+            foreach ($this->modules as $module) {
+                if ($module->isEnabled()) {
+                    // We use TYPO3_REQUEST for compatibility reasons. The object and this method are deprecated anyway, this should be fine.
+                    $module->onSubmit($input, $GLOBALS['TYPO3_REQUEST']);
+                }
+            }
+            // Saving
+            $beUser->writeUC();
+            // Flush fluid template cache
+            $cacheManager = new CacheManager();
+            $cacheManager->setCacheConfigurations($GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']);
+            $cacheManager->getCache('fluid_template')->flush();
+        }
     }
 
     /**
diff --git a/typo3/sysext/adminpanel/Resources/Private/Language/locallang.xlf b/typo3/sysext/adminpanel/Resources/Private/Language/locallang.xlf
new file mode 100644 (file)
index 0000000..053299b
--- /dev/null
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xliff version="1.0" xmlns:t3="http://typo3.org/schemas/xliff">
+       <file t3:id="1520838123" source-language="en" datatype="plaintext" original="messages" date="2018-03-31T08:08:00Z"
+                 product-name="adminpanel">
+               <header/>
+               <body>
+                       <trans-unit id="deprecatedModuleLabel">
+                               <source>General</source>
+                       </trans-unit>
+                       <trans-unit id="settings.label">
+                               <source>Settings</source>
+                       </trans-unit>
+                       <trans-unit id="settings.updateButtonLabel">
+                               <source>Update Settings</source>
+                       </trans-unit>
+               </body>
+       </file>
+</xliff>
index c06aaa8..e2d1e70 100644 (file)
@@ -7,26 +7,14 @@
             <trans-unit id="module.label">
                 <source>Cache</source>
             </trans-unit>
-            <trans-unit id="cache_noCache">
+            <trans-unit id="cache.no_cache">
                 <source>No caching</source>
             </trans-unit>
-            <trans-unit id="cache_doit">
-                <source>Clear cache now!</source>
+            <trans-unit id="cache.clear_current">
+                <source>Clear cache of current page</source>
             </trans-unit>
-            <trans-unit id="cache_clearLevels">
-                <source>Clear levels</source>
-            </trans-unit>
-            <trans-unit id="div_Levels_0">
-                <source>This page</source>
-            </trans-unit>
-            <trans-unit id="div_Levels_1">
-                <source>+ 1 sublevel</source>
-            </trans-unit>
-            <trans-unit id="div_Levels_2">
-                <source>+ 2 sublevels</source>
-            </trans-unit>
-            <trans-unit id="update">
-                <source>Update</source>
+            <trans-unit id="cache.clear_pages">
+                <source>Clear frontend cache</source>
             </trans-unit>
         </body>
     </file>
index f8315d0..c78a527 100644 (file)
@@ -4,6 +4,9 @@
                  product-name="adminpanel">
                <header/>
                <body>
+                       <trans-unit id="module.label">
+                               <source>Edit</source>
+                       </trans-unit>
                        <trans-unit id="displayFieldIcons">
                                <source>Display edit icons</source>
                        </trans-unit>
index 80c0357..a87b6d1 100644 (file)
@@ -6,6 +6,9 @@
             <trans-unit id="module.label">
                 <source>Info</source>
             </trans-unit>
+            <trans-unit id="module.shortinfo">
+                <source>(Load Time: %s ms)</source>
+            </trans-unit>
             <trans-unit id="imagesOnPage">
                 <source>Images on this page</source>
             </trans-unit>
             <trans-unit id="totalParsetime">
                 <source>Total parsetime</source>
             </trans-unit>
+            <trans-unit id="key">
+                <source>Key</source>
+            </trans-unit>
+            <trans-unit id="value">
+                <source>Value</source>
+            </trans-unit>
+            <trans-unit id="sub.general.label">
+                <source>General</source>
+            </trans-unit>
+            <trans-unit id="sub.php.label">
+                <source>PHP</source>
+            </trans-unit>
+            <trans-unit id="sub.request.label">
+                <source>REQUEST</source>
+            </trans-unit>
         </body>
     </file>
 </xliff>
index 9958a75..888f667 100644 (file)
@@ -6,6 +6,9 @@
             <trans-unit id="module.label">
                 <source>TypoScript</source>
             </trans-unit>
+            <trans-unit id="module.shortinfo">
+                <source>(%s Messages)</source>
+            </trans-unit>
             <trans-unit id="treeDisplay">
                 <source>Tree display</source>
             </trans-unit>
@@ -24,6 +27,9 @@
             <trans-unit id="forceTemplateParsing">
                 <source>Force TS Rendering</source>
             </trans-unit>
+            <trans-unit id="sub.waterfall.label">
+                <source>TS Tree</source>
+            </trans-unit>
         </body>
     </file>
 </xliff>
diff --git a/typo3/sysext/adminpanel/Resources/Private/Layouts/Default.html b/typo3/sysext/adminpanel/Resources/Private/Layouts/Default.html
new file mode 100644 (file)
index 0000000..492dd21
--- /dev/null
@@ -0,0 +1,40 @@
+<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" xmlns:core="http://typo3.org/ns/TYPO3/CMS/Core/ViewHelpers" data-namespace-typo3-fluid="true">
+<!-- TYPO3 admin panel start -->
+<f:format.raw>{resources}</f:format.raw>
+<f:if condition="{adminPanelActive}">
+    <f:format.raw>{moduleResources.css}</f:format.raw>
+    <f:format.raw>{moduleResources.js}</f:format.raw>
+</f:if>
+<form id="TSFE_ADMIN_PANEL_FORM" data-typo3-role="typo3-adminPanel" data-typo3-ajax-url="{saveUrl}" class="typo3-kidjls9dksoje typo3-adminPanel{f:if(condition: adminPanelActive, then: ' typo3-adminPanel-active')}">
+
+    <div class="typo3-adminPanel-bar">
+        <div class="typo3-adminPanel-module typo3-adminPanel-module-logo">
+            <div class="typo3-adminPanel-module-trigger">
+                <span class="typo3-adminPanel-module-trigger-icon"><core:icon identifier="information-typo3-version" alternativeMarkupIdentifier="inline"/></span>
+            </div>
+        </div>
+        <f:if condition="{adminPanelActive}">
+            <div class="typo3-adminPanel-module-group">
+                <f:render section="Module" debug="false"/>
+            </div>
+            <f:render section="Settings" debug="false"/>
+        </f:if>
+        <div class="typo3-adminPanel-module typo3-adminPanel-module-toggle">
+            <div class="typo3-adminPanel-module-trigger" data-typo3-role="typo3-adminPanel-trigger" data-typo3-ajax-url="{toggleActiveUrl}">
+                <span class="typo3-adminPanel-module-trigger-icon">
+                    <f:if condition="{adminPanelActive}">
+                        <f:then>
+                            <core:icon identifier="actions-edit-hide" alternativeMarkupIdentifier="inline"/>
+                        </f:then>
+                        <f:else>
+                            <core:icon identifier="actions-edit-unhide" alternativeMarkupIdentifier="inline"/>
+                        </f:else>
+                    </f:if>
+                </span>
+            </div>
+        </div>
+    </div>
+
+</form>
+<!-- TYPO3 admin panel end -->
+</html>
diff --git a/typo3/sysext/adminpanel/Resources/Private/Partials/Data/TableKeyValue.html b/typo3/sysext/adminpanel/Resources/Private/Partials/Data/TableKeyValue.html
new file mode 100644 (file)
index 0000000..e5b5232
--- /dev/null
@@ -0,0 +1,37 @@
+<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
+<f:if condition="{data}">
+    <h2 class="typo3-adminPanel-headline">{label}</h2>
+    <div class="typo3-adminPanel-table-overflow">
+        <table class="typo3-adminPanel-table typo3-adminPanel-table-debug">
+            <thead>
+                <tr>
+                    <th scope="col" class="typo3-adminPanel-table-cell-key"><f:translate key="LLL:EXT:adminpanel/Resources/Private/Language/locallang_info.xlf:key"/></th>
+                    <th scope="col"><f:translate key="LLL:EXT:adminpanel/Resources/Private/Language/locallang_info.xlf:value"/></th>
+                </tr>
+            </thead>
+            <tbody>
+                <f:for each="{data}" as="val" key="key">
+                    <tr>
+                        <th scope="row" class="typo3-adminPanel-table-cell-key">
+                            <f:translate key="{key}" default="{key}" extensionName="adminpanel"/>
+                        </th>
+                        <td>
+                            <f:variable name="typeClass" value="string" />
+                            <f:if condition="{val as integer} === {val}"><f:variable name="typeClass" value="integer" /></f:if>
+                            <f:if condition="{val as float} === {val}"><f:variable name="typeClass" value="float" /></f:if>
+                            <f:switch expression="{typeClass}">
+                                <f:case value="string">
+                                    <pre class="typo3-adminPanel-dump typo3-adminPanel-dump-{typeClass}"><f:if condition="{val}"><f:translate key="{val}" default="{val}" extensionName="adminpanel"/></f:if></pre>
+                                </f:case>
+                                <f:defaultCase>
+                                    <pre class="typo3-adminPanel-dump typo3-adminPanel-dump-{typeClass}">{val}</pre>
+                                </f:defaultCase>
+                            </f:switch>
+                        </td>
+                    </tr>
+                </f:for>
+            </tbody>
+        </table>
+    </div>
+</f:if>
+</html>
diff --git a/typo3/sysext/adminpanel/Resources/Private/Partials/Form/Checkbox.html b/typo3/sysext/adminpanel/Resources/Private/Partials/Form/Checkbox.html
new file mode 100644 (file)
index 0000000..74e5c09
--- /dev/null
@@ -0,0 +1,13 @@
+<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
+<f:if condition="{label} && {name}">
+    <div class="typo3-adminPanel-form-group typo3-adminPanel-form-group-checkbox">
+        <div class="typo3-adminPanel-form-checkbox">
+            <input type="hidden" name="TSFE_ADMIN_PANEL[{name}]" value="0"/>
+            <input type="checkbox" id="{name}" name="TSFE_ADMIN_PANEL[{name}]" value="1" class="typo3-adminPanel-form-checkbox-input"{f:if(condition: value, then:' checked="checked"')} />
+            <label for="{name}" class="typo3-adminPanel-form-checkbox-label">
+                <f:translate key="{label}" default="{label}" extensionName="adminpanel"/>
+            </label>
+        </div>
+    </div>
+</f:if>
+</html>
diff --git a/typo3/sysext/adminpanel/Resources/Private/Partials/Form/DateTime.html b/typo3/sysext/adminpanel/Resources/Private/Partials/Form/DateTime.html
new file mode 100644 (file)
index 0000000..699e481
--- /dev/null
@@ -0,0 +1,16 @@
+<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
+<f:if condition="{label} && {name}">
+    <div class="typo3-adminPanel-form-group">
+        <div class="typo3-adminPanel-form-datetime">
+            <label for="{name}" class="typo3-adminPanel-form-datetime-label">
+                <f:translate key="{label}" default="{label}" extensionName="adminpanel"/>
+            </label>
+            <div class="typo3-adminPanel-form-datetime-input-group">
+                <input type="date" id="{name}-date-hr" class="typo3-adminPanel-form-datetime-input" data-target="{name}"/>
+                <input type="time" id="{name}-time-hr" class="typo3-adminPanel-form-datetime-input" data-target="{name}"/>
+            </div>
+            <input type="hidden" name="TSFE_ADMIN_PANEL[{name}]" id="{name}" value="{value}" />
+        </div>
+    </div>
+</f:if>
+</html>
diff --git a/typo3/sysext/adminpanel/Resources/Private/Partials/Form/Hidden.html b/typo3/sysext/adminpanel/Resources/Private/Partials/Form/Hidden.html
new file mode 100644 (file)
index 0000000..88e8896
--- /dev/null
@@ -0,0 +1,5 @@
+<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
+<f:if condition="{name}">
+    <input type="hidden" name="TSFE_ADMIN_PANEL[{name}]" value="{value}"/>
+</f:if>
+</html>
diff --git a/typo3/sysext/adminpanel/Resources/Private/Partials/Form/Select.html b/typo3/sysext/adminpanel/Resources/Private/Partials/Form/Select.html
new file mode 100644 (file)
index 0000000..ff15fa2
--- /dev/null
@@ -0,0 +1,19 @@
+<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
+<f:if condition="{label} && {name}">
+    <div class="typo3-adminPanel-form-group">
+        <div class="typo3-adminPanel-form-select">
+            <label for="{name}" class="typo3-adminPanel-form-select-label">
+                <f:translate key="{label}" default="{label}" extensionName="adminpanel"/>
+            </label>
+            <select name="TSFE_ADMIN_PANEL[{name}]" id="{name}" class="typo3-adminPanel-form-select-input">
+                <option value="0"></option>
+                <f:for each="{options}" as="option">
+                    <option value="{option.{optionValue}}" {f:if(condition:'{option.{optionValue}} === {value}', then: 'selected')}>
+                        {option.{optionLabel}}
+                    </option>
+                </f:for>
+            </select>
+        </div>
+    </div>
+</f:if>
+</html>
diff --git a/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Cache/ClearCacheButton.html b/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Cache/ClearCacheButton.html
deleted file mode 100644 (file)
index f44eef5..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-<div class="typo3-adminPanel-form-group">
-    <input class="typo3-adminPanel-btn typo3-adminPanel-btn-default"
-           type="submit"
-           name="TSFE_ADMIN_PANEL[action][clearCache]"
-           value="{f:translate(key:'LLL:EXT:adminpanel/Resources/Private/Language/locallang_cache.xlf:cache_doit')}"/>
-</div>
diff --git a/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Cache/ClearLevels.html b/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Cache/ClearLevels.html
deleted file mode 100644 (file)
index 8ef6d63..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-<div class="typo3-adminPanel-form-group">
-    <label for="cache_clearCacheLevels">
-        <f:translate key="LLL:EXT:adminpanel/Resources/Private/Language/locallang_cache.xlf:cache_clearLevels" />
-    </label>
-    <select id="cache_clearCacheLevels" name="TSFE_ADMIN_PANEL[cache_clearCacheLevels]">
-        <option value="0" {f:if(condition:'{cacheLevels} == 0', then:' selected="selected"')} >
-        <f:translate key="LLL:EXT:adminpanel/Resources/Private/Language/locallang_cache.xlf:div_Levels_0" />
-        </option>
-        <option value="1" {f:if(condition:'{cacheLevels} == 1', then:' selected="selected"')}>
-        <f:translate key="LLL:EXT:adminpanel/Resources/Private/Language/locallang_cache.xlf:div_Levels_1" />
-        </option>';
-        <option value="2" {f:if(condition:'{cacheLevels} == 2', then:' selected="selected"')}>
-        <f:translate key="LLL:EXT:adminpanel/Resources/Private/Language/locallang_cache.xlf:div_Levels_2" />
-        </option>
-    </select>
-</div>
diff --git a/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Cache/NoCache.html b/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Cache/NoCache.html
deleted file mode 100644 (file)
index 097c06d..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-<div class="typo3-adminPanel-form-group">
-    <div class="typo3-adminPanel-form-group-checkbox">
-        <input type="hidden" name="TSFE_ADMIN_PANEL[cache_noCache]" value="0"/>
-        <label for="cache_noCache">
-            <input type="checkbox"
-                   id="cache_noCache"
-                   name="TSFE_ADMIN_PANEL[cache_noCache]"
-                   value="1"
-                   {f:if(condition:'{noCache}', then:' checked="checked"')} />
-            <f:translate key="LLL:EXT:adminpanel/Resources/Private/Language/locallang_cache.xlf:cache_noCache"/>
-        </label>
-    </div>
-</div>
diff --git a/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Cache/UpdateButton.html b/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Cache/UpdateButton.html
deleted file mode 100644 (file)
index 2cc732c..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-<div class="typo3-adminPanel-form-group">
-    <input type="hidden" name="TSFE_ADMIN_PANEL[cache_clearCacheId]" value="{currentId}"/>
-    <input class="typo3-adminPanel-btn typo3-adminPanel-btn-default"
-           type="submit"
-           value="{f:translate(key:'LLL:EXT:adminpanel/Resources/Private/Language/locallang_cache.xlf:update')}"/>
-</div>
diff --git a/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Edit/BackendButton.html b/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Edit/BackendButton.html
deleted file mode 100644 (file)
index a0c9e6f..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-<div class="typo3-adminPanel-form-group">
-       <a class="typo3-adminPanel-btn typo3-adminPanel-btn-default typo3-adminPanel-btn-openBackend"
-                href="#"
-                data-pageUid="{script.pageUid}"
-                data-pageModule="{script.pageModule}"
-                data-t3BeSitenameMd5="{script.t3BeSitenameMd5}"
-                data-backendScript="{script.backendScript}">
-               <f:translate key="LLL:EXT:adminpanel/Resources/Private/Language/locallang_edit.xlf:openAB"/>
-       </a>
-</div>
diff --git a/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Edit/FeEdit.html b/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Edit/FeEdit.html
deleted file mode 100644 (file)
index 7ee5bfb..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-<f:if condition="{feEdit}">
-       <div class="typo3-adminPanel-form-group">
-               <div class="typo3-adminPanel-form-group-checkbox">
-                       <f:form.hidden name="TSFE_ADMIN_PANEL[edit_displayFieldIcons]" value="0"/>
-                       <label for="edit_displayFieldIcons">
-                               <f:form.checkbox
-                                       name="TSFE_ADMIN_PANEL[edit_displayFieldIcons]"
-                                       value="1" checked="{display.fieldIcons}"
-                                       id="edit_displayFieldIcons"/>
-                               <f:translate key="LLL:EXT:adminpanel/Resources/Private/Language/locallang_edit.xlf:displayFieldIcons"/>
-                       </label>
-               </div>
-               <div class="typo3-adminPanel-form-group-checkbox">
-                       <f:form.hidden name="TSFE_ADMIN_PANEL[edit_displayIcons]" value="0"/>
-                       <label for="edit_displayIcons">
-                               <f:form.checkbox
-                                       name="TSFE_ADMIN_PANEL[edit_displayIcons]"
-                                       value="1"
-                                       checked="{display.displayIcons}"
-                                       id="edit_displayIcons"/>
-                               <f:translate key="LLL:EXT:adminpanel/Resources/Private/Language/locallang_edit.xlf:displayIcons"/>
-                       </label>
-               </div>
-       </div>
-</f:if>
diff --git a/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Edit/Toolbar.html b/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Edit/Toolbar.html
deleted file mode 100644 (file)
index e64dfee..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<f:format.raw>{toolbar}</f:format.raw>
diff --git a/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Info/DocumentSize.html b/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Info/DocumentSize.html
deleted file mode 100644 (file)
index c86bbae..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-<tr>
-    <td><strong>
-        <f:translate
-                key="LLL:EXT:adminpanel/Resources/Private/Language/locallang_info.xlf:DocumentSize"/>
-    </strong></td>
-    <td>{info.documentSize}</td>
-</tr>
diff --git a/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Info/FeUserGroupList.html b/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Info/FeUserGroupList.html
deleted file mode 100644 (file)
index 3275864..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-<tr>
-    <td>
-        <f:translate key="LLL:EXT:adminpanel/Resources/Private/Language/locallang_info.xlf:groupList"/>
-    </td>
-    <td>{info.groupList}</td>
-</tr>
diff --git a/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Info/FrontendUser.html b/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Info/FrontendUser.html
deleted file mode 100644 (file)
index 08a11db..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-<f:if condition="{info.feUser.uid} > 0">
-    <tr>
-        <td>
-            <f:translate key="LLL:EXT:adminpanel/Resources/Private/Language/locallang_info.xlf:feuserName"/>
-        </td>
-        <td>{info.feUser.username}</td>
-    </tr>
-    <tr>
-        <td>
-            <f:translate key="LLL:EXT:adminpanel/Resources/Private/Language/locallang_info.xlf:feuserId"/>
-        </td>
-        <td>{info.feUser.uid}</td>
-    </tr>
-</f:if>
diff --git a/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Info/ImagesOnPage.html b/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Info/ImagesOnPage.html
deleted file mode 100644 (file)
index 5e0d659..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-<f:if condition="{info.imagesOnPage.total} > 0">
-    <tr>
-        <td><strong>
-            <f:translate
-                    key="LLL:EXT:adminpanel/Resources/Private/Language/locallang_info.xlf:imagesOnPage"/>
-        </strong></td>
-        <td>{info.imagesOnPage.total}</td>
-    </tr>
-
-    <f:for each="{info.imagesOnPage.files}" as="file">
-        <tr>
-            <td>&nbsp; {file.name}</td>
-            <td>{file.sizeHuman}</td>
-        </tr>
-    </f:for>
-
-    <tr>
-        <td><strong>
-            <f:translate
-                    key="LLL:EXT:adminpanel/Resources/Private/Language/locallang_info.xlf:imagesSize"/>
-        </strong></td>
-        <td>{info.imagesOnPage.totalSize}</td>
-    </tr>
-</f:if>
diff --git a/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Info/Page.html b/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Info/Page.html
deleted file mode 100644 (file)
index a554924..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-<tr>
-    <td>
-        <f:translate key="LLL:EXT:adminpanel/Resources/Private/Language/locallang_info.xlf:pageUid"/>
-    </td>
-    <td>{info.pageUid}</td>
-</tr>
-<tr>
-    <td>
-        <f:translate key="LLL:EXT:adminpanel/Resources/Private/Language/locallang_info.xlf:pageType"/>
-    </td>
-    <td>{info.pageType}</td>
-</tr>
diff --git a/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Info/PageCache.html b/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Info/PageCache.html
deleted file mode 100644 (file)
index 9c0191c..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-<tr>
-    <td>
-        <f:translate key="LLL:EXT:adminpanel/Resources/Private/Language/locallang_info.xlf:noCache"/>
-    </td>
-    <td>
-        <f:translate
-                key="LLL:EXT:adminpanel/Resources/Private/Language/locallang_info.xlf:noCache_{f:if(condition:'{info.noCache}',then:'no',else:'yes')}"/>
-    </td>
-</tr>
diff --git a/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Info/TotalParsetime.html b/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Info/TotalParsetime.html
deleted file mode 100644 (file)
index fc7cf0b..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-<tr>
-    <td><strong>
-        <f:translate key="LLL:EXT:adminpanel/Resources/Private/Language/locallang_info.xlf:totalParsetime"/>
-    </strong></td>
-    <td>{info.totalParsetime} ms</td>
-</tr>
diff --git a/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Info/UserIntObjects.html b/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Info/UserIntObjects.html
deleted file mode 100644 (file)
index 7b4b390..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-<tr>
-    <td>
-        <f:translate key="LLL:EXT:adminpanel/Resources/Private/Language/locallang_info.xlf:countUserInt"/>
-    </td>
-    <td>{info.countUserInt}</td>
-</tr>
diff --git a/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Item.html b/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Item.html
new file mode 100644 (file)
index 0000000..545dcbd
--- /dev/null
@@ -0,0 +1,66 @@
+<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" xmlns:core="http://typo3.org/ns/TYPO3/CMS/Core/ViewHelpers" data-namespace-typo3-fluid="true">
+<div class="typo3-adminPanel-module{f:if(condition: uid, then: ' typo3-adminPanel-module-{uid}')}">
+    <div class="typo3-adminPanel-module-trigger" data-typo3-role="typo3-adminPanel-module-trigger">
+        <f:if condition="{icon}"><span class="typo3-adminPanel-module-trigger-icon">{icon -> f:format.raw()}</span></f:if>
+        <f:if condition="{label}"><span class="typo3-adminPanel-module-trigger-label">{label}</span></f:if>
+        <f:if condition="{information}"><span class="typo3-adminPanel-module-trigger-information">{information}</span></f:if>
+    </div>
+    <f:if condition="{mainContent} || {module.subModules}">
+        <div class="typo3-adminPanel-content" data-typo3-role="typo3-adminPanel-content">
+            <div class="typo3-adminPanel-content-header">
+                <div class="typo3-adminPanel-content-header-item typo3-adminPanel-content-header-title">
+                    <f:if condition="{icon}"><span class="typo3-adminPanel-content-header-title-icon">{icon -> f:format.raw()}</span></f:if>
+                    <f:if condition="{label}"><span class="typo3-adminPanel-content-header-title-label">{label}</span></f:if>
+                </div>
+                <div class="typo3-adminPanel-content-nav" data-typo3-role="typo3-adminPanel-content-tabs">
+                    <f:for each="{module.subModules}" as="sub" iteration="iteration">
+                        <a href="#" class="typo3-adminPanel-content-header-item{f:if(condition: iteration.isFirst, then: ' typo3-adminPanel-content-header-item-active')}" data-typo3-role="typo3-adminPanel-content-tab" data-typo3-tab-target="{sub.identifier}">{sub.label}</a>
+                    </f:for>
+                </div>
+                <f:if condition="{module.hasSubmoduleSettings}">
+                    <button type="button" class="typo3-adminPanel-content-header-item typo3-adminPanel-content-header-settings" data-typo3-role="typo3-adminPanel-content-settings">
+                        <core:icon identifier="actions-system-extension-configure" alternativeMarkupIdentifier="inline"/>
+                    </button>
+                </f:if>
+                <button type="button" class="typo3-adminPanel-content-header-item typo3-adminPanel-content-header-close" data-typo3-role="typo3-adminPanel-content-close">
+                    <core:icon identifier="actions-close" alternativeMarkupIdentifier="inline"/>
+                </button>
+            </div>
+            <f:if condition="{module.hasSubmoduleSettings}">
+                <div class="typo3-adminPanel-content-settings">
+                    <f:for each="{module.subModules}" as="sub">
+                        <f:if condition="{sub.settings}">
+                            <div class="typo3-adminPanel-content-settings-group">
+                                <h4 class="typo3-adminPanel-headline">Settings Group</h4>
+                                <f:format.raw>
+                                    {sub.settings}
+                                </f:format.raw>
+                            </div>
+                        </f:if>
+                    </f:for>
+                    <div class="typo3-adminPanel-form-group">
+                        <f:form.button class="typo3-adminPanel-btn typo3-adminPanel-btn-primary" data="{typo3-role: 'typo3-adminPanel-saveButton'}">Save</f:form.button>
+                    </div>
+                </div>
+            </f:if>
+            <div class="typo3-adminPanel-content-main">
+                <f:if condition="{mainContent}">
+                    <f:then>
+                        {mainContent -> f:format.raw()}
+                    </f:then>
+                    <f:else>
+                        <div class="typo3-adminPanel-content-panes">
+                            <f:for each="{module.subModules}" as="sub" iteration="subModulesIterator">
+                                <div class="typo3-adminPanel-content-panes-item{f:if(condition:'{subModulesIterator.isFirst}',then:' typo3-adminPanel-content-panes-item-active')}" data-typo3-role="typo3-adminPanel-content-pane" data-typo3-tab-id="{sub.identifier}">
+                                    <f:if condition="{sub.label}"><h1 class="typo3-adminPanel-headline">{sub.label}</h1></f:if>
+                                    <f:format.raw>{sub.content}</f:format.raw>
+                                </div>
+                            </f:for>
+                        </div>
+                    </f:else>
+                </f:if>
+            </div>
+        </div>
+    </f:if>
+</div>
+</html>
diff --git a/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Preview/FluidDebug.html b/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Preview/FluidDebug.html
deleted file mode 100644 (file)
index 3a63ee3..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-<div class="typo3-adminPanel-form-group-checkbox">
-    <input type="hidden" name="TSFE_ADMIN_PANEL[preview_showFluidDebug]" value="0"/>
-    <label for="preview_showFluidDebug">
-        <input type="checkbox"
-               id="preview_showFluidDebug"
-               name="TSFE_ADMIN_PANEL[preview_showFluidDebug]"
-               value="1"
-               {f:if(condition: '{showFluidDebug}', then:'checked="checked"')}
-        />
-        <f:translate key="LLL:EXT:adminpanel/Resources/Private/Language/locallang_preview.xlf:showFluidDebug"/>
-    </label>
-</div>
diff --git a/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Preview/FrontendUserGroup.html b/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Preview/FrontendUserGroup.html
deleted file mode 100644 (file)
index d529e30..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-<div class="typo3-adminPanel-form-group">
-    <label for="preview_simulateUserGroup">
-        <f:translate
-                key="LLL:EXT:adminpanel/Resources/Private/Language/locallang_preview.xlf:simulateUserGroup"/>
-    </label>
-
-    <select name="TSFE_ADMIN_PANEL[preview_simulateUserGroup]"
-            id="preview_simulateUserGroup">
-        <option value="0"></option>
-        <f:for each="{frontendUserGroups.availableGroups}" as="group">
-            <option value="{group.uid}"
-                    {f:if(condition:'{group.uid} == {frontendUserGroups.selected}', then: 'selected="selected"')}>
-            {group.title}
-            </option>
-        </f:for>
-    </select>
-</div>
diff --git a/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Preview/HiddenPages.html b/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Preview/HiddenPages.html
deleted file mode 100644 (file)
index b4c9b02..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-<div class="typo3-adminPanel-form-group-checkbox">
-    <input type="hidden" name="TSFE_ADMIN_PANEL[preview_showHiddenPages]" value="0"/>
-    <label for="preview_showHiddenPages">
-        <input type="checkbox"
-               id="preview_showHiddenPages"
-               name="TSFE_ADMIN_PANEL[preview_showHiddenPages]"
-               value="1"
-               {f:if(condition: '{showHiddenPages}', then:'checked="checked"')}
-        />
-        <f:translate key="LLL:EXT:adminpanel/Resources/Private/Language/locallang_preview.xlf:showHiddenPages"/>
-    </label>
-</div>
diff --git a/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Preview/HiddenRecords.html b/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Preview/HiddenRecords.html
deleted file mode 100644 (file)
index 336aeb3..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-<div class="typo3-adminPanel-form-group-checkbox">
-    <input type="hidden" name="TSFE_ADMIN_PANEL[preview_showHiddenRecords]" value="0"/>
-    <label for="preview_showHiddenRecords">
-        <input type="checkbox"
-               id="preview_showHiddenRecords"
-               name="TSFE_ADMIN_PANEL[preview_showHiddenRecords]"
-               value="1"
-               {f:if(condition: '{showHiddenRecords}', then:'checked="checked"')}
-        />
-        <f:translate
-                key="LLL:EXT:adminpanel/Resources/Private/Language/locallang_preview.xlf:showHiddenRecords"/>
-    </label>
-</div>
diff --git a/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Preview/ShowHiddenElements.html b/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Preview/ShowHiddenElements.html
deleted file mode 100644 (file)
index 9e204a3..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<div class="typo3-adminPanel-form-group">
-    <f:render partial="Modules/Preview/HiddenPages" arguments="{showHiddenPages: show.hiddenPages}" debug="false"/>
-    <f:render partial="Modules/Preview/HiddenRecords" arguments="{showHiddenRecords: show.hiddenRecords}" debug="false"/>
-    <f:render partial="Modules/Preview/FluidDebug" arguments="{showFluidDebug: show.fluidDebug}" debug="false"/>
-</div>
\ No newline at end of file
diff --git a/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Preview/SimulateDate.html b/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/Preview/SimulateDate.html
deleted file mode 100644 (file)
index af3b9b9..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-<div class="typo3-adminPanel-form-group">
-    <label for="preview_simulateDate">
-        <f:translate key="LLL:EXT:adminpanel/Resources/Private/Language/locallang_preview.xlf:simulateDate"/>
-    </label>
-    <input type="text"
-           id="preview_simulateDate"
-           name="TSFE_ADMIN_PANEL[preview_simulateDate]_hr"
-           onchange="TSFEtypo3FormFieldGet('TSFE_ADMIN_PANEL[preview_simulateDate]', 'datetime', '', 1,0);"/>
-    <input type="hidden" name="TSFE_ADMIN_PANEL[preview_simulateDate]" value="{simulateDate}"/>
-</div>
diff --git a/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/TsDebug/DisplayContent.html b/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/TsDebug/DisplayContent.html
deleted file mode 100644 (file)
index 68aa3e8..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-<div class="typo3-adminPanel-form-group-checkbox">
-    <input type="hidden" name="TSFE_ADMIN_PANEL[tsdebug_displayContent]" value="0"/>
-    <label for="tsdebug_displayContent">
-        <input type="checkbox"
-               id="tsdebug_displayContent"
-               name="TSFE_ADMIN_PANEL[tsdebug_displayContent]"
-               value="1"
-               {f:if(condition:'{display.content}', then:' checked="checked"')} />
-        <f:translate key="LLL:EXT:adminpanel/Resources/Private/Language/locallang_tsdebug.xlf:displayContent"/>
-    </label>
-</div>
diff --git a/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/TsDebug/DisplayMessages.html b/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/TsDebug/DisplayMessages.html
deleted file mode 100644 (file)
index 6961fa3..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-<div class="typo3-adminPanel-form-group-checkbox">
-    <input type="hidden" name="TSFE_ADMIN_PANEL[tsdebug_displayMessages]" value="0"/>
-    <label for="tsdebug_displayMessages">
-        <input type="checkbox"
-               id="tsdebug_displayMessages"
-               name="TSFE_ADMIN_PANEL[tsdebug_displayMessages]"
-               value="1"
-               {f:if(condition:'{display.messages}', then:' checked="checked"')} />
-        <f:translate key="LLL:EXT:adminpanel/Resources/Private/Language/locallang_tsdebug.xlf:displayMessages"/>
-    </label>
-</div>
diff --git a/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/TsDebug/DisplayTimes.html b/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/TsDebug/DisplayTimes.html
deleted file mode 100644 (file)
index 7e216be..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-<div class="typo3-adminPanel-form-group-checkbox">
-    <input type="hidden" name="TSFE_ADMIN_PANEL[tsdebug_displayTimes]" value="0"/>
-    <label for="tsdebug_displayTimes">
-        <input type="checkbox"
-               id="tsdebug_displayTimes"
-               name="TSFE_ADMIN_PANEL[tsdebug_displayTimes]"
-               value="1"
-               {f:if(condition:'{display.times}', then:' checked="checked"')} />
-        <f:translate key="LLL:EXT:adminpanel/Resources/Private/Language/locallang_tsdebug.xlf:displayTimes"/>
-    </label>
-</div>
diff --git a/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/TsDebug/ForceTemplateParsing.html b/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/TsDebug/ForceTemplateParsing.html
deleted file mode 100644 (file)
index 5c97600..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-<div class="typo3-adminPanel-form-group-checkbox">
-    <input type="hidden" name="TSFE_ADMIN_PANEL[tsdebug_forceTemplateParsing]" value="0"/>
-    <label for="tsdebug_forceTemplateParsing">
-        <input type="checkbox"
-               id="tsdebug_forceTemplateParsing"
-               name="TSFE_ADMIN_PANEL[tsdebug_forceTemplateParsing]"
-               value="1"
-               {f:if(condition:'{forceTemplateParsing}', then:' checked="checked"')} />
-        <f:translate key="LLL:EXT:adminpanel/Resources/Private/Language/locallang_tsdebug.xlf:forceTemplateParsing"/>
-    </label>
-</div>
diff --git a/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/TsDebug/TrackContentRendering.html b/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/TsDebug/TrackContentRendering.html
deleted file mode 100644 (file)
index f56d09e..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-<div class="typo3-adminPanel-form-group-checkbox">
-    <input type="hidden" name="TSFE_ADMIN_PANEL[tsdebug_LR]" value="0"/>
-    <label for="tsdebug_LR">
-        <input type="checkbox"
-               id="tsdebug_LR"
-               name="TSFE_ADMIN_PANEL[tsdebug_LR]"
-               value="1"
-               {f:if(condition:'{trackContentRendering}', then:' checked="checked"')} />
-        <f:translate key="LLL:EXT:adminpanel/Resources/Private/Language/locallang_tsdebug.xlf:trackContentRendering"/>
-    </label>
-</div>
diff --git a/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/TsDebug/Tree.html b/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/TsDebug/Tree.html
deleted file mode 100644 (file)
index 7fed5cb..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-<div class="typo3-adminPanel-form-group-checkbox">
-    <input type="hidden" name="TSFE_ADMIN_PANEL[tsdebug_tree]" value="0"/>
-    <label for="tsdebug_tree">
-        <input type="checkbox"
-               id="tsdebug_tree"
-               name="TSFE_ADMIN_PANEL[tsdebug_tree]"
-               value="1"
-               {f:if(condition:'{tree}', then:' checked="checked"')} />
-        <f:translate key="LLL:EXT:adminpanel/Resources/Private/Language/locallang_tsdebug.xlf:treeDisplay"/>
-    </label>
-</div>
diff --git a/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/TsDebug/TypoScriptLog.html b/typo3/sysext/adminpanel/Resources/Private/Partials/Modules/TsDebug/TypoScriptLog.html
deleted file mode 100644 (file)
index 938a9c2..0000000
+++ /dev/null
@@ -1 +0,0 @@
-{typoScriptLog -> f:format.raw()}
diff --git a/typo3/sysext/adminpanel/Resources/Private/Templates/Main.html b/typo3/sysext/adminpanel/Resources/Private/Templates/Main.html
new file mode 100644 (file)
index 0000000..205fd58
--- /dev/null
@@ -0,0 +1,55 @@
+<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" xmlns:core="http://typo3.org/ns/TYPO3/CMS/Core/ViewHelpers" data-namespace-typo3-fluid="true">
+<f:layout name="Default"/>
+<f:section name="Module">
+
+    <f:for each="{modules}" as="module" iteration="iteration">
+        <f:if condition="{module.subModules}">
+            <f:variable name="uid">{iteration.index}</f:variable>
+            <f:variable name="icon"><core:icon identifier="{module.iconIdentifier}" alternativeMarkupIdentifier="inline"/></f:variable>
+            <f:variable name="label">{module.label}</f:variable>
+            <f:variable name="information">{module.shortInfo}</f:variable>
+            <f:render partial="Modules/Item" arguments="{module: module, uid: uid, icon: icon, label: label, information: information}" debug="false"/>
+        </f:if>
+    </f:for>
+
+    <f:if condition="{hookObjectModuleContent}">
+        <f:variable name="uid">hook</f:variable>
+        <f:variable name="icon"><core:icon identifier="actions-window-open" alternativeMarkupIdentifier="inline"/></f:variable>
+        <f:variable name="label"><f:translate key="LLL:EXT:adminpanel/Resources/Private/Language/locallang.xlf:deprecatedModuleLabel"/></f:variable>
+        <f:variable name="mainContent">{hookObjectModuleContent}</f:variable>
+        <f:render partial="Modules/Item" arguments="{uid: uid, icon: icon, label: label, mainContent: mainContent}" debug="false"/>
+    </f:if>
+
+</f:section>
+<f:section name="Settings">
+
+    <f:variable name="uid">settings</f:variable>
+    <f:variable name="icon"><core:icon identifier="actions-system-extension-configure" alternativeMarkupIdentifier="inline"/></f:variable>
+    <f:variable name="label"><f:translate key="LLL:EXT:adminpanel/Resources/Private/Language/locallang.xlf:settings.label"/></f:variable>
+    <f:variable name="information">{module.shortInfo}</f:variable>
+    <f:variable name="mainContent">
+        <h1 class="typo3-adminPanel-headline"><f:translate key="LLL:EXT:adminpanel/Resources/Private/Language/locallang.xlf:settings.label"/></h1>
+        <div class="typo3-adminPanel-card-group">
+            <f:for each="{modules}" as="module">
+                <f:if condition="{module.settings}">
+                    <div class="typo3-adminPanel-card">
+                        <div class="typo3-adminPanel-card-header">
+                            <h2 class="typo3-adminPanel-card-header-headline">
+                                <span class="typo3-adminPanel-card-header-icon"><core:icon identifier="{module.iconIdentifier}" alternativeMarkupIdentifier="inline"/></span>
+                                <span class="typo3-adminPanel-card-header-text">{module.label}</span>
+                            </h2>
+                        </div>
+                        <div class="typo3-adminPanel-card-body"><f:format.raw>{module.settings}</f:format.raw></div>
+                    </div>
+                </f:if>
+            </f:for>
+        </div>
+        <div class="typo3-adminPanel-form-group">
+            <button data-typo3-role="typo3-adminPanel-saveButton" class="typo3-adminPanel-btn typo3-adminPanel-btn-primary">
+                <f:translate key="LLL:EXT:adminpanel/Resources/Private/Language/locallang.xlf:settings.updateButtonLabel"/>
+            </button>
+        </div>
+    </f:variable>
+    <f:render partial="Modules/Item" arguments="{uid: uid, icon: icon, label: label, information: information, mainContent: mainContent}" debug="false"/>
+</f:section>
+</html>
diff --git a/typo3/sysext/adminpanel/Resources/Private/Templates/Modules/Cache.html b/typo3/sysext/adminpanel/Resources/Private/Templates/Modules/Cache.html
deleted file mode 100644 (file)
index 643eb49..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-<f:if condition="{isEnabled} == 1">
-    <f:render partial="Modules/Cache/NoCache" debug="false" arguments="{_all}"/>
-    <f:render partial="Modules/Cache/ClearLevels" debug="false" arguments="{_all}"/>
-    <f:render partial="Modules/Cache/UpdateButton" debug="false" arguments="{_all}"/>
-    <f:render partial="Modules/Cache/ClearCacheButton" debug="false"/>
-</f:if>
diff --git a/typo3/sysext/adminpanel/Resources/Private/Templates/Modules/Edit.html b/typo3/sysext/adminpanel/Resources/Private/Templates/Modules/Edit.html
deleted file mode 100644 (file)
index 669e352..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<f:if condition="{display.edit}">
-       <f:render partial="Modules/Edit/FeEdit" arguments="{_all}" debug="false" />
-       <f:render partial="Modules/Edit/Toolbar" arguments="{_all}" debug="false" />
-       <f:render partial="Modules/Edit/BackendButton" arguments="{_all}" debug="false" />
-</f:if>
diff --git a/typo3/sysext/adminpanel/Resources/Private/Templates/Modules/Info.html b/typo3/sysext/adminpanel/Resources/Private/Templates/Modules/Info.html
deleted file mode 100644 (file)
index d3d9cb0..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-<div class="typo3-adminPanel-table-overflow">
-    <table class="typo3-adminPanel-table">
-        <f:if condition="{info.noCache}">
-            <f:render partial="Modules/Info/ImagesOnPage" arguments="{_all}" debug="false" />
-            <f:render partial="Modules/Info/DocumentSize" arguments="{_all}" debug="false" />
-            <tr>
-                <td>&nbsp;</td>
-                <td>&nbsp;</td>
-            </tr>
-        </f:if>
-        <f:render partial="Modules/Info/Page" arguments="{_all}" debug="false" />
-        <f:render partial="Modules/Info/FeUserGroupList" arguments="{_all}" debug="false" />
-        <f:render partial="Modules/Info/PageCache" arguments="{_all}" debug="false" />
-        <f:render partial="Modules/Info/UserIntObjects" arguments="{_all}" debug="false" />
-        <f:render partial="Modules/Info/FrontendUser" arguments="{_all}" debug="false" />
-        <f:render partial="Modules/Info/TotalParsetime" arguments="{_all}" debug="false" />
-    </table>
-</div>
diff --git a/typo3/sysext/adminpanel/Resources/Private/Templates/Modules/Info/General.html b/typo3/sysext/adminpanel/Resources/Private/Templates/Modules/Info/General.html
new file mode 100644 (file)
index 0000000..007930e
--- /dev/null
@@ -0,0 +1,87 @@
+<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
+<f:if condition="{info.noCache}">
+
+    <f:if condition="{info.imagesOnPage.total} > 0">
+        <h2 class="typo3-adminPanel-headline">Images</h2>
+        <div class="typo3-adminPanel-table-overflow">
+            <table class="typo3-adminPanel-table typo3-adminPanel-table-debug">
+                <thead>
+                    <tr>
+                        <th scope="col" class="typo3-adminPanel-table-cell-key"><f:translate key="LLL:EXT:adminpanel/Resources/Private/Language/locallang_info.xlf:key"/></th>
+                        <th scope="col"><f:translate key="LLL:EXT:adminpanel/Resources/Private/Language/locallang_info.xlf:value"/></th>
+                    </tr>
+                </thead>
+                <tbody>
+                    <tr>
+                        <th scope="row" class="typo3-adminPanel-table-cell-key"><f:translate key="LLL:EXT:adminpanel/Resources/Private/Language/locallang_info.xlf:imagesOnPage"/></th>
+                        <td>
+                            <f:variable name="typeClass" value="string" />
+                            <f:if condition="{info.imagesOnPage.total as integer} === {info.imagesOnPage.total}"><f:variable name="typeClass" value="integer" /></f:if>
+                            <f:if condition="{info.imagesOnPage.total as float} === {info.imagesOnPage.total}"><f:variable name="typeClass" value="float" /></f:if>
+                            <pre class="typo3-adminPanel-dump typo3-adminPanel-dump-{typeClass}">{info.imagesOnPage.total}</pre>
+                        </td>
+                    </tr>
+                    <f:for each="{info.imagesOnPage.files}" as="file">
+                        <tr>
+                            <th scope="row" class="typo3-adminPanel-table-cell-key">
+                                {file.name}
+                            </th>
+                            <td>
+                                <f:variable name="typeClass" value="string" />
+                                <f:if condition="{file.sizeHuman as integer} === {file.sizeHuman}"><f:variable name="typeClass" value="integer" /></f:if>
+                                <f:if condition="{file.sizeHuman as float} === {file.sizeHuman}"><f:variable name="typeClass" value="float" /></f:if>
+                                <pre class="typo3-adminPanel-dump typo3-adminPanel-dump-{typeClass}">{file.sizeHuman}</pre>
+                            </td>
+                        </tr>
+                    </f:for>
+                    <tr>
+                        <th scope="row" class="typo3-adminPanel-table-cell-key"><f:translate key="LLL:EXT:adminpanel/Resources/Private/Language/locallang_info.xlf:imagesSize"/></th>
+                        <td>
+                            <f:variable name="typeClass" value="string" />
+                            <f:if condition="{info.imagesOnPage.totalSize as integer} === {info.imagesOnPage.totalSize}"><f:variable name="typeClass" value="integer" /></f:if>
+                            <f:if condition="{info.imagesOnPage.totalSize as float} === {info.imagesOnPage.totalSize}"><f:variable name="typeClass" value="float" /></f:if>
+                            <pre class="typo3-adminPanel-dump typo3-adminPanel-dump-{typeClass}">{info.imagesOnPage.totalSize}</pre>
+                        </td>
+                    </tr>
+                </tbody>
+            </table>
+        </div>
+    </f:if>
+
+    <f:render partial="Data/TableKeyValue" arguments="{label: 'Document Size', data: '{
+        \'LLL:EXT:adminpanel/Resources/Private/Language/locallang_info.xlf:DocumentSize\': \'{info.documentSize as integer}\'
+        }'}" debug="false"/>
+
+</f:if>
+
+<f:render partial="Data/TableKeyValue" arguments="{label: 'Page', data: '{
+    \'LLL:EXT:adminpanel/Resources/Private/Language/locallang_info.xlf:pageUid\': info.pageUid,
+    \'LLL:EXT:adminpanel/Resources/Private/Language/locallang_info.xlf:pageType\': info.pageType
+    }'}" debug="false"/>
+
+<f:render partial="Data/TableKeyValue" arguments="{label: 'Frontend User Group', data: '{
+    \'LLL:EXT:adminpanel/Resources/Private/Language/locallang_info.xlf:groupList\': info.groupList
+    }'}" debug="false"/>
+
+<f:variable name="noCacheLabel">LLL:EXT:adminpanel/Resources/Private/Language/locallang_info.xlf:noCache_no</f:variable>
+<f:if condition="{info.noCache}"><f:variable name="noCacheLabel">LLL:EXT:adminpanel/Resources/Private/Language/locallang_info.xlf:noCache_yes</f:variable></f:if>
+<f:render partial="Data/TableKeyValue" arguments="{label: 'Cache', data: '{
+    \'LLL:EXT:adminpanel/Resources/Private/Language/locallang_info.xlf:noCache\': noCacheLabel
+    }'}" debug="false"/>
+
+<f:render partial="Data/TableKeyValue" arguments="{label: 'UserIntObjects', data: '{
+    \'LLL:EXT:adminpanel/Resources/Private/Language/locallang_info.xlf:countUserInt\': info.countUserInt
+    }'}" debug="false"/>
+
+<f:if condition="{info.feUser.uid} > 0">
+    <f:render partial="Data/TableKeyValue" arguments="{label: 'Frontend User', data: '{
+        \'LLL:EXT:adminpanel/Resources/Private/Language/locallang_info.xlf:feuserName\': info.feUser.username,
+        \'LLL:EXT:adminpanel/Resources/Private/Language/locallang_info.xlf:feuserId\': info.feUser.uid,
+        }'}" debug="false"/>
+</f:if>
+
+<f:render partial="Data/TableKeyValue" arguments="{label: 'Total Parsetime', data: '{
+    \'LLL:EXT:adminpanel/Resources/Private/Language/locallang_info.xlf:totalParsetime\': \'{info.totalParsetime} ms\'
+    }'}" debug="false"/>
+
+</html>
diff --git a/typo3/sysext/adminpanel/Resources/Private/Templates/Modules/Info/PhpInfo.html b/typo3/sysext/adminpanel/Resources/Private/Templates/Modules/Info/PhpInfo.html
new file mode 100644 (file)
index 0000000..62c1b49
--- /dev/null
@@ -0,0 +1,6 @@
+<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
+<f:render partial="Data/TableKeyValue" arguments="{label: 'General', data: general}" debug="false"/>
+<f:render partial="Data/TableKeyValue" arguments="{label: 'Constants', data: constants.user}" debug="false"/>
+<h2 class="typo3-adminPanel-headline">Extensions</h2>
+<pre class="typo3-adminPanel-dump">{loadedExtensions}</pre>
+</html>
diff --git a/typo3/sysext/adminpanel/Resources/Private/Templates/Modules/Info/RequestInformation.html b/typo3/sysext/adminpanel/Resources/Private/Templates/Modules/Info/RequestInformation.html
new file mode 100644 (file)
index 0000000..6479ac9
--- /dev/null
@@ -0,0 +1,7 @@
+<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
+<f:render partial="Data/TableKeyValue" arguments="{label: '$_GET', data: get}" debug="false"/>
+<f:render partial="Data/TableKeyValue" arguments="{label: '$_POST', data: post}" debug="false"/>
+<f:render partial="Data/TableKeyValue" arguments="{label: '$_COOKIE', data: cookie}" debug="false"/>
+<f:render partial="Data/TableKeyValue" arguments="{label: '$_SESSION', data: session}" debug="false"/>
+<f:render partial="Data/TableKeyValue" arguments="{label: '$_SERVER', data: server}" debug="false"/>
+</html>
diff --git a/typo3/sysext/adminpanel/Resources/Private/Templates/Modules/Preview.html b/typo3/sysext/adminpanel/Resources/Private/Templates/Modules/Preview.html
deleted file mode 100644 (file)
index 2eac4ee..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-<f:render partial="Modules/Preview/ShowHiddenElements" arguments="{show: show}" debug="false" />
-<f:render partial="Modules/Preview/SimulateDate" arguments="{simulateDate: simulateDate}" debug="false" />
-<f:render partial="Modules/Preview/FrontendUserGroup.html" arguments="{frontendUserGroups: frontendUserGroups}" debug="false"/>
diff --git a/typo3/sysext/adminpanel/Resources/Private/Templates/Modules/Settings/Cache.html b/typo3/sysext/adminpanel/Resources/Private/Templates/Modules/Settings/Cache.html
new file mode 100644 (file)
index 0000000..089e59d
--- /dev/null
@@ -0,0 +1,18 @@
+<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
+<f:render partial="Form/Checkbox" arguments="{
+    label: 'LLL:EXT:adminpanel/Resources/Private/Language/locallang_cache.xlf:cache.no_cache',
+    name: 'cache_noCache',
+    value: noCache }" debug="false"/>
+<div class="typo3-adminPanel-form-group">
+    <f:form.button class="typo3-adminPanel-btn typo3-adminPanel-btn-default" data="{'typo3-ajax-url': clearCurrentPageCacheUrl, 'typo3-role': 'clearCacheButton'}" type="button">
+        {f:translate(key:'LLL:EXT:adminpanel/Resources/Private/Language/locallang_cache.xlf:cache.clear_current')}
+    </f:form.button>
+</div>
+<f:if condition="{clearPageCacheUrl}">
+    <div class="typo3-adminPanel-form-group">
+        <f:form.button class="typo3-adminPanel-btn typo3-adminPanel-btn-default" data="{'typo3-ajax-url': clearPageCacheUrl, 'typo3-role': 'clearCacheButton'}" type="button">
+            {f:translate(key:'LLL:EXT:adminpanel/Resources/Private/Language/locallang_cache.xlf:cache.clear_pages')}
+        </f:form.button>
+    </div>
+</f:if>
+</html>
diff --git a/typo3/sysext/adminpanel/Resources/Private/Templates/Modules/Settings/Edit.html b/typo3/sysext/adminpanel/Resources/Private/Templates/Modules/Settings/Edit.html
new file mode 100644 (file)
index 0000000..46a6a6e
--- /dev/null
@@ -0,0 +1,18 @@
+<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
+<f:if condition="{feEdit}">
+    <f:render partial="Form/Checkbox" arguments="{
+        label: 'LLL:EXT:adminpanel/Resources/Private/Language/locallang_edit.xlf:displayFieldIcons',
+        name: 'edit_displayFieldIcons',
+        value: display.fieldIcons }" debug="false"/>
+    <f:render partial="Form/Checkbox" arguments="{
+        label: 'LLL:EXT:adminpanel/Resources/Private/Language/locallang_edit.xlf:displayIcons',
+        name: 'edit_displayIcons',
+        value: display.displayIcons }" debug="false"/>
+</f:if>
+<f:format.raw>{toolbar}</f:format.raw>
+<div class="typo3-adminPanel-form-group">
+    <a class="typo3-adminPanel-btn typo3-adminPanel-btn-default typo3-adminPanel-btn-openBackend" href="#" data-pageUid="{script.pageUid}" data-pageModule="{script.pageModule}" data-t3BeSitenameMd5="{script.t3BeSitenameMd5}" data-backendScript="{script.backendScript}">
+        <f:translate key="LLL:EXT:adminpanel/Resources/Private/Language/locallang_edit.xlf:openAB"/>
+    </a>
+</div>
+</html>
diff --git a/typo3/sysext/adminpanel/Resources/Private/Templates/Modules/Settings/Preview.html b/typo3/sysext/adminpanel/Resources/Private/Templates/Modules/Settings/Preview.html
new file mode 100644 (file)
index 0000000..01ba493
--- /dev/null
@@ -0,0 +1,28 @@
+<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
+<f:render partial="Form/Checkbox" arguments="{
+    label: 'LLL:EXT:adminpanel/Resources/Private/Language/locallang_preview.xlf:showHiddenPages',
+    name: 'preview_showHiddenPages',
+    value: show.hiddenPages }" debug="false"/>
+<f:render partial="Form/Checkbox" arguments="{
+    label: 'LLL:EXT:adminpanel/Resources/Private/Language/locallang_preview.xlf:showHiddenRecords',
+    name: 'preview_showHiddenRecords',
+    value: show.hiddenRecords }" debug="false"/>
+<f:render partial="Form/Checkbox" arguments="{
+    label: 'LLL:EXT:adminpanel/Resources/Private/Language/locallang_preview.xlf:showFluidDebug',
+    name: 'preview_showFluidDebug',
+    value: show.fluidDebug }" debug="false"/>
+<f:render partial="Form/Hidden" arguments="{
+    name: 'preview_clearCacheId',
+    value: show.pageId }" debug="false"/>
+<f:render partial="Form/DateTime" arguments="{
+    label: 'LLL:EXT:adminpanel/Resources/Private/Language/locallang_preview.xlf:simulateDate',
+    name: 'preview_simulateDate',
+    value: simulateDate }" debug="false"/>
+<f:render partial="Form/Select" arguments="{
+    label: 'LLL:EXT:adminpanel/Resources/Private/Language/locallang_preview.xlf:simulateUserGroup',
+    name: 'preview_simulateUserGroup',
+    options: frontendUserGroups.availableGroups,
+    optionValue: 'uid',
+    optionLabel: 'title',
+    value: frontendUserGroups.selected }" debug="false"/>
+</html>
diff --git a/typo3/sysext/adminpanel/Resources/Private/Templates/Modules/TsDebug.html b/typo3/sysext/adminpanel/Resources/Private/Templates/Modules/TsDebug.html
deleted file mode 100644 (file)
index 2f97161..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-<f:if condition="{isEnabled} == 1">
-    <div class="typo3-adminPanel-form-group">
-        <f:render partial="Modules/TsDebug/Tree" debug="false" arguments="{_all}"/>
-        <f:render partial="Modules/TsDebug/DisplayTimes" debug="false" arguments="{_all}"/>
-        <f:render partial="Modules/TsDebug/DisplayMessages" debug="false" arguments="{_all}"/>
-        <f:render partial="Modules/TsDebug/TrackContentRendering" debug="false" arguments="{_all}"/>
-        <f:render partial="Modules/TsDebug/DisplayContent" debug="false" arguments="{_all}"/>
-        <f:render partial="Modules/TsDebug/ForceTemplateParsing" debug="false" arguments="{_all}"/>
-        <f:render partial="Modules/TsDebug/TypoScriptLog" debug="false" arguments="{_all}"/>
-    </div>
-</f:if>
diff --git a/typo3/sysext/adminpanel/Resources/Private/Templates/Modules/TsDebug/TypoScript.html b/typo3/sysext/adminpanel/Resources/Private/Templates/Modules/TsDebug/TypoScript.html
new file mode 100644 (file)
index 0000000..ed0131d
--- /dev/null
@@ -0,0 +1,3 @@
+<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
+{typoScriptLog -> f:format.raw()}
+</html>
diff --git a/typo3/sysext/adminpanel/Resources/Private/Templates/Modules/TsDebug/TypoScriptSettings.html b/typo3/sysext/adminpanel/Resources/Private/Templates/Modules/TsDebug/TypoScriptSettings.html
new file mode 100644 (file)
index 0000000..6684b36
--- /dev/null
@@ -0,0 +1,26 @@
+<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
+<f:render partial="Form/Checkbox" arguments="{
+    label: 'LLL:EXT:adminpanel/Resources/Private/Language/locallang_tsdebug.xlf:treeDisplay',
+    name: 'tsdebug_tree',
+    value: tree }" debug="false"/>
+<f:render partial="Form/Checkbox" arguments="{
+    label: 'LLL:EXT:adminpanel/Resources/Private/Language/locallang_tsdebug.xlf:displayTimes',
+    name: 'tsdebug_displayTimes',
+    value: display.times }" debug="false"/>
+<f:render partial="Form/Checkbox" arguments="{
+    label: 'LLL:EXT:adminpanel/Resources/Private/Language/locallang_tsdebug.xlf:displayMessages',
+    name: 'tsdebug_displayMessages',
+    value: display.messages }" debug="false"/>
+<f:render partial="Form/Checkbox" arguments="{
+    label: 'LLL:EXT:adminpanel/Resources/Private/Language/locallang_tsdebug.xlf:trackContentRendering',
+    name: 'tsdebug_LR',
+    value: trackContentRendering }" debug="false"/>
+<f:render partial="Form/Checkbox" arguments="{
+    label: 'LLL:EXT:adminpanel/Resources/Private/Language/locallang_tsdebug.xlf:displayContent',
+    name: 'tsdebug_displayContent',
+    value: display.content }" debug="false"/>
+<f:render partial="Form/Checkbox" arguments="{
+    label: 'LLL:EXT:adminpanel/Resources/Private/Language/locallang_tsdebug.xlf:forceTemplateParsing',
+    name: 'tsdebug_forceTemplateParsing',
+    value: forceTemplateParsing }" debug="false"/>
+</html>
index abfbf33..a3813f9 100644 (file)
@@ -10,4 +10,4 @@
  * 
  * The TYPO3 project - inspiring people to share!
  */
-#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .icon,.typo3-editPanel-btn .icon,.typo3-editPanel-link .icon{position:relative;display:inline-block;overflow:hidden;white-space:nowrap;vertical-align:-22%}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .icon img,#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .icon svg,.typo3-editPanel-btn .icon img,.typo3-editPanel-btn .icon svg,.typo3-editPanel-link .icon img,.typo3-editPanel-link .icon svg{display:block;height:100%;width:100%;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .icon *,.typo3-editPanel-btn .icon *,.typo3-editPanel-link .icon *{display:block;line-height:inherit}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .icon-markup,.typo3-editPanel-btn .icon-markup,.typo3-editPanel-link .icon-markup{position:absolute;display:block;text-align:center;top:0;left:0;right:0;bottom:0}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .icon-overlay,.typo3-editPanel-btn .icon-overlay,.typo3-editPanel-link .icon-overlay{position:absolute;bottom:0;right:0;height:68.75%;width:68.75%;text-align:center}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .icon-color,.typo3-editPanel-btn .icon-color,.typo3-editPanel-link .icon-color{fill:currentColor}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .icon-spin .icon-markup,.typo3-editPanel-btn .icon-spin .icon-markup,.typo3-editPanel-link .icon-spin .icon-markup{-webkit-animation:icon-spin 2s infinite linear;animation:icon-spin 2s infinite linear}@-webkit-keyframes icon-spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes icon-spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .icon-state-disabled .icon-markup,.typo3-editPanel-btn .icon-state-disabled .icon-markup,.typo3-editPanel-link .icon-state-disabled .icon-markup{opacity:.5}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .icon-size-small,.typo3-editPanel-btn .icon-size-small,.typo3-editPanel-link .icon-size-small{height:16px;width:16px;line-height:16px}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .icon-size-small .icon-unify,.typo3-editPanel-btn .icon-size-small .icon-unify,.typo3-editPanel-link .icon-size-small .icon-unify{line-height:16px;font-size:14px}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .icon-size-small .icon-overlay .icon-unify,.typo3-editPanel-btn .icon-size-small .icon-overlay .icon-unify,.typo3-editPanel-link .icon-size-small .icon-overlay .icon-unify{line-height:10px;font-size:9px}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .icon-size-default,.typo3-editPanel-btn .icon-size-default,.typo3-editPanel-link .icon-size-default{height:32px;width:32px;line-height:32px}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .icon-size-default .icon-unify,.typo3-editPanel-btn .icon-size-default .icon-unify,.typo3-editPanel-link .icon-size-default .icon-unify{line-height:32px;font-size:28px}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .icon-size-default .icon-overlay .icon-unify,.typo3-editPanel-btn .icon-size-default .icon-overlay .icon-unify,.typo3-editPanel-link .icon-size-default .icon-overlay .icon-unify{line-height:20px;font-size:18px}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .icon-size-large,.typo3-editPanel-btn .icon-size-large,.typo3-editPanel-link .icon-size-large{height:48px;width:48px;line-height:48px}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .icon-size-large .icon-unify,.typo3-editPanel-btn .icon-size-large .icon-unify,.typo3-editPanel-link .icon-size-large .icon-unify{line-height:48px;font-size:42px}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .icon-size-large .icon-overlay .icon-unify,.typo3-editPanel-btn .icon-size-large .icon-overlay .icon-unify,.typo3-editPanel-link .icon-size-large .icon-overlay .icon-unify{line-height:30px;font-size:26px}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .icon-actions-edit-copy-release,#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .icon-actions-edit-cut-release,#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .icon-status-dialog-error,#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .icon-status-status-current,#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .icon-status-status-permission-denied,.typo3-editPanel-btn .icon-actions-edit-copy-release,.typo3-editPanel-btn .icon-actions-edit-cut-release,.typo3-editPanel-btn .icon-status-dialog-error,.typo3-editPanel-btn .icon-status-status-current,.typo3-editPanel-btn .icon-status-status-permission-denied,.typo3-editPanel-link .icon-actions-edit-copy-release,.typo3-editPanel-link .icon-actions-edit-cut-release,.typo3-editPanel-link .icon-status-dialog-error,.typo3-editPanel-link .icon-status-status-current,.typo3-editPanel-link .icon-status-status-permission-denied{color:#c83c3c}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .icon-status-status-sorting-light-asc,#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .icon-status-status-sorting-light-desc,.typo3-editPanel-btn .icon-status-status-sorting-light-asc,.typo3-editPanel-btn .icon-status-status-sorting-light-desc,.typo3-editPanel-link .icon-status-status-sorting-light-asc,.typo3-editPanel-link .icon-status-status-sorting-light-desc{color:#fff}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .icon-status-status-sorting-asc,#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .icon-status-status-sorting-desc,.typo3-editPanel-btn .icon-status-status-sorting-asc,.typo3-editPanel-btn .icon-status-status-sorting-desc,.typo3-editPanel-link .icon-status-status-sorting-asc,.typo3-editPanel-link .icon-status-status-sorting-desc{color:#737373}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .icon-status-dialog-information,.typo3-editPanel-btn .icon-status-dialog-information,.typo3-editPanel-link .icon-status-dialog-information{color:#6daae0}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .icon-status-dialog-ok,#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .icon-status-status-permission-granted,.typo3-editPanel-btn .icon-status-dialog-ok,.typo3-editPanel-btn .icon-status-status-permission-granted,.typo3-editPanel-link .icon-status-dialog-ok,.typo3-editPanel-link .icon-status-status-permission-granted{color:#79a548}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .icon-status-dialog-notification,.typo3-editPanel-btn .icon-status-dialog-notification,.typo3-editPanel-link .icon-status-dialog-notification{color:#333}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .icon-status-dialog-warning,.typo3-editPanel-btn .icon-status-dialog-warning,.typo3-editPanel-link .icon-status-dialog-warning{color:#e8a33d}@font-face{font-family:TYPO3FontAwesome;src:url(../../../../backend/Resources/Public/Fonts/FontAwesome/fontawesome-webfont.eot?v=4.6.3);src:url(../../../../backend/Resources/Public/Fonts/FontAwesome/fontawesome-webfont.eot?#iefix&v=4.6.3) format("embedded-opentype"),url(../../../../backend/Resources/Public/Fonts/FontAwesome/fontawesome-webfont.woff2?v=4.6.3) format("woff2"),url(../../../../backend/Resources/Public/Fonts/FontAwesome/fontawesome-webfont.woff?v=4.6.3) format("woff"),url(../../../../backend/Resources/Public/Fonts/FontAwesome/fontawesome-webfont.ttf?v=4.6.3) format("truetype"),url(../../../../backend/Resources/Public/Fonts/FontAwesome/fontawesome-webfont.svg?v=4.6.3#fontawesomeregular) format("svg");font-weight:400;font-style:normal}#TSFE_ADMIN_PANEL_FORM .fa:before,.typo3-editPanel .fa:before,.typo3-feedit-element .fa:before{display:inline-block;font:normal normal normal 14px/1 TYPO3FontAwesome;font-size:15px;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-transform:translate(0,0);transform:translate(0,0)}#TSFE_ADMIN_PANEL_FORM .fa-pencil:before,.typo3-editPanel .fa-pencil:before,.typo3-feedit-element .fa-pencil:before{content:"\f040"}#TSFE_ADMIN_PANEL_FORM .fa-angle-up:before,.typo3-editPanel .fa-angle-up:before,.typo3-feedit-element .fa-angle-up:before{content:"\f106"}#TSFE_ADMIN_PANEL_FORM .fa-angle-down:before,.typo3-editPanel .fa-angle-down:before,.typo3-feedit-element .fa-angle-down:before{content:"\f107"}#TSFE_ADMIN_PANEL_FORM .fa-toggle-off:before,.typo3-editPanel .fa-toggle-off:before,.typo3-feedit-element .fa-toggle-off:before{content:"\f204"}#TSFE_ADMIN_PANEL_FORM .fa-toggle-on:before,.typo3-editPanel .fa-toggle-on:before,.typo3-feedit-element .fa-toggle-on:before{content:"\f205"}#TSFE_ADMIN_PANEL_FORM .fa-google-plus-square:before,.typo3-editPanel .fa-google-plus-square:before,.typo3-feedit-element .fa-google-plus-square:before{content:"\f0d4"}#TSFE_ADMIN_PANEL_FORM .fa-trash:before,.typo3-editPanel .fa-trash:before,.typo3-feedit-element .fa-trash:before{content:"\f1f8"}#TSFE_ADMIN_PANEL_FORM .fa-history:before,.typo3-editPanel .fa-history:before,.typo3-feedit-element .fa-history:before{content:"\f1da"}#TSFE_ADMIN_PANEL_FORM .fa-list-alt:before,.typo3-editPanel .fa-list-alt:before,.typo3-feedit-element .fa-list-alt:before{content:"\f022"}#TSFE_ADMIN_PANEL_FORM .fa-plus-square:before,.typo3-editPanel .fa-plus-square:before,.typo3-feedit-element .fa-plus-square:before{content:"\f0fe"}#TSFE_ADMIN_PANEL_FORM .fa-arrows:before,.typo3-editPanel .fa-arrows:before,.typo3-feedit-element .fa-arrows:before{content:"\f047"}#TSFE_ADMIN_PANEL_FORM .fa-exclamation-circle:before,.typo3-editPanel .fa-exclamation-circle:before,.typo3-feedit-element .fa-exclamation-circle:before{content:"\f06a"}#TSFE_ADMIN_PANEL_FORM .fa-exclamation-triangle:before,.typo3-editPanel .fa-exclamation-triangle:before,.typo3-feedit-element .fa-exclamation-triangle:before{content:"\f071"}#TSFE_ADMIN_PANEL_FORM .fa-info-circle:before,.typo3-editPanel .fa-info-circle:before,.typo3-feedit-element .fa-info-circle:before{content:"\f05a"}#TSFE_ADMIN_PANEL_FORM .fa-caret-down:before,.typo3-editPanel .fa-caret-down:before,.typo3-feedit-element .fa-caret-down:before{content:"\f0d7"}#TSFE_ADMIN_PANEL_FORM .fa-caret-up:before,.typo3-editPanel .fa-caret-up:before,.typo3-feedit-element .fa-caret-up:before{content:"\f0d8"}#TSFE_ADMIN_PANEL_FORM .fa-bolt:before,.typo3-editPanel .fa-bolt:before,.typo3-feedit-element .fa-bolt:before{content:"\f0e7"}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-section-title-identifier:before{display:inline-block;font:normal normal normal 14px/1 TYPO3FontAwesome;font-size:15px;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-transform:translate(0,0);transform:translate(0,0)}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel,.typo3-editPanel{background-color:#fafafa;color:#333;font-family:sans-serif;font-size:12px;line-height:1.35em}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel a,.typo3-editPanel a{color:inherit;text-decoration:none}#TSFE_ADMIN_PANEL_FORM{display:block!important;position:fixed;bottom:0;left:0;max-width:100%;max-height:100%;z-index:10002;padding:0;margin:0}#TSFE_ADMIN_PANEL_FORM *{box-sizing:border-box}#TSFE_ADMIN_PANEL_FORM *,#TSFE_ADMIN_PANEL_FORM :active,#TSFE_ADMIN_PANEL_FORM :focus,#TSFE_ADMIN_PANEL_FORM :hover{outline:0}#TSFE_ADMIN_PANEL_FORM :after,#TSFE_ADMIN_PANEL_FORM :before{box-sizing:border-box}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel{border:1px solid #cacaca;max-height:100vh;max-width:100%;min-width:280px;border-left:0;border-bottom:0;border-top-left-radius:2px;display:-webkit-box;display:-webkit-flex;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;flex-direction:column}#TSFE_ADMIN_PANEL_FORM #typo3AdminPanelCollapse{display:none}#TSFE_ADMIN_PANEL_FORM #typo3AdminPanelEnable:checked+#typo3AdminPanelCollapse+.typo3-adminPanel .typo3-adminPanel-header .typo3-adminPanel-header-enable-enabled{display:inline}#TSFE_ADMIN_PANEL_FORM #typo3AdminPanelEnable:checked+#typo3AdminPanelCollapse+.typo3-adminPanel .typo3-adminPanel-header .typo3-adminPanel-header-collapse{display:block}#TSFE_ADMIN_PANEL_FORM #typo3AdminPanelCollapse:checked+.typo3-adminPanel .typo3-adminPanel-actions,#TSFE_ADMIN_PANEL_FORM #typo3AdminPanelCollapse:checked+.typo3-adminPanel .typo3-adminPanel-body{display:none}#TSFE_ADMIN_PANEL_FORM #typo3AdminPanelCollapse:checked+.typo3-adminPanel .typo3-adminPanel-header .typo3-adminPanel-header-collapse-enabled{display:inline}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-header{position:relative;background-color:#333;color:#fafafa;padding:1em 3em}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-header .typo3-adminPanel-header-user:before{content:':';margin-right:.5em}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-header .typo3-adminPanel-header-collapse,#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-header .typo3-adminPanel-header-enable{position:absolute;cursor:pointer;top:50%;left:0;padding:1em;-webkit-transform:translate(0,-50%);transform:translate(0,-50%)}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-header .typo3-adminPanel-header-collapse{display:none;left:auto;right:0}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-header .typo3-adminPanel-header-enable-enabled{color:#79a548}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-header .typo3-adminPanel-header-enable-disabled{color:#c83c3c}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-header .typo3-adminPanel-header-collapse-enabled{display:none}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-actions{text-align:right;padding:0 1em .75em;background-color:#333;color:#fafafa}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-body{height:100%;overflow:auto}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-body>.typo3-adminPanel-section-title:first-child{border-top:none}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-section-title{position:relative;overflow:hidden;border-top:1px solid #bbb;background-color:#eee;padding:.75em 3em .75em 1em}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-section-title:hover{background-color:#ddd}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-section-title a{position:relative;display:block;padding:.75em 3em .75em 1em;margin:-.75em -3em -.75em -1em}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-section-title-identifier{position:absolute;top:50%;right:0;padding:1em;-webkit-transform:translate(0,-50%);transform:translate(0,-50%)}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-section-title-identifier:before{content:"\f105"}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-section-open .typo3-adminPanel-section-title-identifier:before{content:"\f107 "}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-section-body{padding:.75em 1em}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel label{display:block;font-weight:400;padding:0;margin:0;overflow:hidden}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel input[type=text],#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel select{display:block;width:100%;padding:.5em;border:1px solid #ccc;margin:.5em 0;font-size:inherit}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel input[type=text]:focus,#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel input[type=text]:hover,#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel select:focus,#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel select:hover{border-color:#aaa}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-form-group{margin:1em 0}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-form-group-checkbox,#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-form-group-radio{margin:.5em 0}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-form-group-checkbox label,#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-form-group-radio label{padding-left:20px}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-form-group-checkbox input[type=checkbox],#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-form-group-checkbox input[type=radio],#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-form-group-radio input[type=checkbox],#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-form-group-radio input[type=radio]{float:left;padding:0;margin:1px 0 0 -20px}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-table-overflow{max-width:100%;margin:1em 0;overflow-x:auto}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-table{width:100%;border:1px solid #ccc;border-collapse:collapse;border-spacing:0}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-table td,#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-table th{text-align:left;overflow:hidden;position:relative;vertical-align:top;padding:.75em}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-table thead tr{background-color:rgba(0,0,0,.15)}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-table thead td,#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-table thead th{font-weight:400}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-table tbody tr:nth-of-type(odd){background-color:rgba(0,0,0,.05)}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-table-cell-content{word-wrap:break-word}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-table-cell-nowrap{white-space:nowrap}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-logRow-highlight{background-color:#fcd3cf}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .stackPointer{color:maroon;vertical-align:top}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-btn{display:inline-block;margin-bottom:0;padding:6px 8px;border:1px solid transparent;border-radius:0;font-weight:400;line-height:1.5;text-align:center;vertical-align:middle;touch-action:manipulation;cursor:pointer;white-space:nowrap;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-btn:active,#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-btn:focus,#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-btn:hover{outline:0}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-btn-default{color:#333;background-color:#eee;border-color:#bbb;cursor:pointer}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-btn-default:hover{background-color:#c4c4c4}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-btn-dark{color:#fafafa;background-color:#555;border-color:rgba(0,0,0,.5);cursor:pointer}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-btn-dark:hover{background-color:#444}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-btn-group{position:relative;display:inline-block;vertical-align:middle}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .typo3-adminPanel-btn-group .typo3-adminPanel-btn+.typo3-adminPanel-btn{margin-left:-1px}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .treeline-icon{display:inline-block;margin-right:2px;padding:0;height:18px;width:16px;white-space:nowrap;overflow:hidden;vertical-align:middle}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .treeline-icon:after,#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .treeline-icon:before{position:absolute;content:'';margin-left:7px}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .treeline-icon:before{top:0;height:100%;width:2px;margin-left:7px;border-left:1px dotted #666}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .treeline-icon:after{border-top:1px dotted #666;height:2px;width:8px;margin-top:8px}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .treeline-icon-jointop:before{top:50%}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .treeline-icon-joinbottom:before{height:26px;margin-top:-8px}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .treeline-icon-line:after{display:none}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .treeline-icon-blank{display:none}#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .treeline-icon-clear:after,#TSFE_ADMIN_PANEL_FORM .typo3-adminPanel .treeline-icon-clear:before{display:none}.typo3-feedit-element{border:1px solid #cacaca;margin:1em 0}.typo3-editPanel{display:block!important;border-top:1px solid #cacaca;padding:.5em}.typo3-editPanel .typo3-editPanel-label{margin-left:1.5em;display:inline-block;vertical-align:middle}.typo3-editPanel .typo3-adminPanel-btn,.typo3-editPanel .typo3-editPanel-btn{display:inline-block!important;margin-bottom:0;padding:6px 8px;line-height:1.5em;border:1px solid transparent;border-radius:0;font-weight:400;text-align:center;vertical-align:middle;touch-action:manipulation;cursor:pointer;white-space:nowrap;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.typo3-editPanel .typo3-adminPanel-btn:active,.typo3-editPanel .typo3-adminPanel-btn:focus,.typo3-editPanel .typo3-adminPanel-btn:hover,.typo3-editPanel .typo3-editPanel-btn:active,.typo3-editPanel .typo3-editPanel-btn:focus,.typo3-editPanel .typo3-editPanel-btn:hover{outline:0}.typo3-editPanel .typo3-adminPanel-btn-default,.typo3-editPanel .typo3-editPanel-btn-default{color:#333;background-color:#eee;border-color:#bbb;cursor:pointer}.typo3-editPanel .typo3-adminPanel-btn-default:hover,.typo3-editPanel .typo3-editPanel-btn-default:hover{background-color:#c4c4c4}.typo3-editPanel .typo3-adminPanel-form-group,.typo3-editPanel .typo3-editPanel-form-group{margin-right:.5em;display:inline-block}.typo3-editPanel .typo3-adminPanel-btn-group,.typo3-editPanel .typo3-editPanel-btn-group{position:relative;display:inline-block;vertical-align:middle}.typo3-editPanel .typo3-adminPanel-btn-group .typo3-adminPanel-btn+.typo3-adminPanel-btn,.typo3-editPanel .typo3-adminPanel-btn-group .typo3-editPanel-btn+.typo3-editPanel-btn,.typo3-editPanel .typo3-editPanel-btn-group .typo3-adminPanel-btn+.typo3-adminPanel-btn,.typo3-editPanel .typo3-editPanel-btn-group .typo3-editPanel-btn+.typo3-editPanel-btn{margin-left:-1px}.typo3-adminPanel-btn,.typo3-editPanel-btn{display:inline-block!important}.typo3-feedit-element-hidden{border-color:#ebc975}.typo3-feedit-element-hidden .typo3-editPanel{border-top-color:#ebc975;background-color:#f8ecce}.typo3-feedit-element-hidden .typo3-editPanel .typo3-editPanel-btn-default{border-color:#e5b848;background-color:#f2dba1}.typo3-feedit-element-hidden .typo3-editPanel .typo3-editPanel-btn-default:hover{background-color:#eed28b}
\ No newline at end of file
+@font-face{font-family:TYPO3FontAwesome;src:url(../../../../../../typo3/sysext/backend/Resources/Public/Fonts/FontAwesome/fontawesome-webfont.eot?v=4.6.3);src:url(../../../../../../typo3/sysext/backend/Resources/Public/Fonts/FontAwesome/fontawesome-webfont.eot?#iefix&v=4.6.3) format("embedded-opentype"),url(../../../../../../typo3/sysext/backend/Resources/Public/Fonts/FontAwesome/fontawesome-webfont.woff2?v=4.6.3) format("woff2"),url(../../../../../../typo3/sysext/backend/Resources/Public/Fonts/FontAwesome/fontawesome-webfont.woff?v=4.6.3) format("woff"),url(../../../../../../typo3/sysext/backend/Resources/Public/Fonts/FontAwesome/fontawesome-webfont.ttf?v=4.6.3) format("truetype"),url(../../../../../../typo3/sysext/backend/Resources/Public/Fonts/FontAwesome/fontawesome-webfont.svg?v=4.6.3#fontawesomeregular) format("svg");font-weight:400;font-style:normal}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel{z-index:99990}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel *{background:0 0;border:0;box-shadow:none;box-sizing:border-box;vertical-align:baseline;letter-spacing:normal;width:auto;height:auto;font-family:Verdana,Arial,Helvetica,sans-serif;font-size:12px;font-weight:400;white-space:normal;margin:0;padding:0}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel *,#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel :active,#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel :focus,#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel :hover{outline:0}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .icon{position:relative;display:inline-block;overflow:hidden;white-space:nowrap;vertical-align:-22%}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .icon img,#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .icon svg{display:block;height:100%;width:100%;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .icon *{display:block;line-height:inherit}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .icon-markup{position:absolute;display:block;text-align:center;top:0;left:0;right:0;bottom:0}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .icon-overlay{position:absolute;bottom:0;right:0;height:68.75%;width:68.75%;text-align:center}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .icon-color{fill:currentColor}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .icon-spin .icon-markup{-webkit-animation:icon-spin 2s infinite linear;animation:icon-spin 2s infinite linear}@-webkit-keyframes icon-spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes icon-spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .icon-state-disabled .icon-markup{opacity:.5}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .icon-size-small{height:16px;width:16px;line-height:16px}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .icon-size-small .icon-unify{line-height:16px;font-size:14px}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .icon-size-small .icon-overlay .icon-unify{line-height:10px;font-size:9px}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .icon-size-default{height:32px;width:32px;line-height:32px}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .icon-size-default .icon-unify{line-height:32px;font-size:28px}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .icon-size-default .icon-overlay .icon-unify{line-height:20px;font-size:18px}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .icon-size-large{height:48px;width:48px;line-height:48px}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .icon-size-large .icon-unify{line-height:48px;font-size:42px}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .icon-size-large .icon-overlay .icon-unify{line-height:30px;font-size:26px}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .icon-actions-edit-copy-release,#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .icon-actions-edit-cut-release,#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .icon-status-dialog-error,#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .icon-status-status-current,#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .icon-status-status-permission-denied{color:#c83c3c}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .icon-status-status-sorting-light-asc,#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .icon-status-status-sorting-light-desc{color:#fff}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .icon-status-status-sorting-asc,#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .icon-status-status-sorting-desc{color:#737373}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .icon-status-dialog-information{color:#6daae0}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .icon-status-dialog-ok,#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .icon-status-status-permission-granted{color:#79a548}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .icon-status-dialog-notification{color:#333}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .icon-status-dialog-warning{color:#e8a33d}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-backdrop{z-index:99991;content:'';position:fixed;top:0;left:0;right:0;bottom:0;background-color:rgba(0,0,0,.5)}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-bar{z-index:99992;display:-webkit-box;display:-webkit-flex;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row;flex-flow:row;-webkit-box-pack:stretch;-webkit-justify-content:stretch;justify-content:stretch;position:fixed;bottom:0;left:auto;right:0;height:37px;background-color:#424242;color:#fff;border-bottom:1px solid #383838}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel.typo3-adminPanel-active .typo3-adminPanel-bar{left:0}@media (min-width:768px){#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-bar{right:20px}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel.typo3-adminPanel-active .typo3-adminPanel-bar{left:20px}}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-module{display:-webkit-box;display:-webkit-flex;display:flex;padding:0 10px;-webkit-box-align:center;-webkit-align-items:center;align-items:center;border-right:1px solid #383838}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-module-settings{margin-left:auto}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-module-logo+.typo3-adminPanel-module-toggle{border-left:none}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-module-settings .typo3-adminPanel-module-trigger-label{display:none}@media (min-width:768px){#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-module-settings .typo3-adminPanel-module-trigger-label{display:block}}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-module-settings,#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-module-toggle{border-left:1px solid #383838;border-right:none}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-module-group{width:100%;overflow:hidden;display:-webkit-box;display:-webkit-flex;display:flex}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-module-trigger{display:-webkit-box;display:-webkit-flex;display:flex;-webkit-box-align:center;-webkit-align-items:center;align-items:center;padding:0 10px;margin-left:-10px;margin-right:-10px;font-size:12px;color:#fff;height:36px}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-module-trigger>span{white-space:nowrap}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-module-trigger>span+span{margin-left:4px}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-module-active .typo3-adminPanel-module-trigger{background-color:#525252}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel [data-typo3-role=typo3-adminPanel-module-trigger],#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel [data-typo3-role=typo3-adminPanel-trigger]{cursor:pointer}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel [data-typo3-role=typo3-adminPanel-module-trigger]:focus,#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel [data-typo3-role=typo3-adminPanel-module-trigger]:hover,#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel [data-typo3-role=typo3-adminPanel-trigger]:focus,#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel [data-typo3-role=typo3-adminPanel-trigger]:hover{background-color:#525252}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-module-trigger-icon .icon-color{fill:currentColor}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-module-trigger-icon .icon-actions-edit-hide{color:#629755}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-module-trigger-icon .icon-actions-edit-unhide{color:#c83c3c}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-module-trigger-information{display:none;opacity:.5}@media (min-width:768px){#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-module-trigger-information{display:block}}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-content{display:none;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;flex-direction:column;position:fixed;bottom:37px;top:20vh;left:20px;right:20px;background-color:#fafafa;color:#333;border-bottom:1px solid #383838}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-content-main{position:relative;padding:20px;height:100%;overflow:auto}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-content-main>:first-child{margin-top:0}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-content-main>:last-child{margin-bottom:0}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-module-active .typo3-adminPanel-content{display:-webkit-box;display:-webkit-flex;display:flex}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-content-header{position:relative;display:-webkit-box;display:-webkit-flex;display:flex;-webkit-box-align:center;-webkit-align-items:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;justify-content:space-between;height:37px;-webkit-flex-shrink:0;flex-shrink:0;color:#333;background-color:#eaeaea}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-content-header:before{content:'';position:absolute;bottom:0;left:0;right:0;height:1px;background-color:#dadada}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-content-header-item{display:-webkit-box;display:-webkit-flex;display:flex;-webkit-box-align:center;-webkit-align-items:center;align-items:center;height:37px;padding:0 10px;border-right:1px solid #dadada;border-bottom:1px solid #dadada}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel a.typo3-adminPanel-content-header-item{color:inherit;text-decoration:none;position:relative}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel a.typo3-adminPanel-content-header-item:focus,#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel a.typo3-adminPanel-content-header-item:hover{background-color:#e1e1e1}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel a.typo3-adminPanel-content-header-item.typo3-adminPanel-content-header-item-active{background-color:#fafafa}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel a.typo3-adminPanel-content-header-item.typo3-adminPanel-content-header-item-active:before{content:'';position:absolute;bottom:-1px;left:0;right:0;height:1px;background-color:#fafafa}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-content-header-title{position:relative;color:#fff;background-color:#424242;border-right:1px solid #383838}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-content-header-title:before{content:'';position:absolute;bottom:-1px;left:0;right:0;height:1px;background-color:#5e5e5e}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-content-header-title>span+span{margin-left:4px}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-content-header-close,#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-content-header-settings{cursor:pointer;border-right:0;border-left:1px solid #dadada}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-content-nav{width:100%;overflow:hidden;display:-webkit-box;display:-webkit-flex;display:flex}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-content-settings{-webkit-flex-shrink:0;flex-shrink:0;max-height:50%;overflow-y:auto;display:none;background-color:#fafafa;padding:20px;border-bottom:1px solid #dadada;box-shadow:0 0 1px rgba(0,0,0,.1)}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-content-settings.typo3-adminPanel-content-settings-active{display:block}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-content-settings-group>:first-child,#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-content-settings>:first-child{margin-top:0}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-content-settings-group>:last-child,#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-content-settings>:last-child{margin-bottom:0}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-content-settings-group+.typo3-adminPanel-content-settings-group{margin-top:20px;padding-top:20px;border-top:1px solid rgba(0,0,0,.1)}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-content-panes{position:absolute;top:0;bottom:0;left:0;right:0;display:-webkit-box;display:-webkit-flex;display:flex}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-content-panes-item{display:none;overflow:auto;height:100%;width:100%;padding:20px}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-content-panes-item>:first-child{margin-top:0}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-content-panes-item>:last-child{margin-bottom:0}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-content-panes-item-active{display:block}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-row{display:-webkit-box;display:-webkit-flex;display:flex;-webkit-flex-wrap:wrap;flex-wrap:wrap;padding:.25em 0;margin-left:-.75em;margin-right:-.75em}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-row-header>*{font-weight:700}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-col{padding:.25em .75em;word-break:break-all}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-col-1{-webkit-box-flex:0;-webkit-flex:0 0 8.33333333%;flex:0 0 8.33333333%;max-width:8.33333333%}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-col-2{-webkit-box-flex:0;-webkit-flex:0 0 16.66666667%;flex:0 0 16.66666667%;max-width:16.66666667%}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-col-3{-webkit-box-flex:0;-webkit-flex:0 0 25%;flex:0 0 25%;max-width:25%}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-col-4{-webkit-box-flex:0;-webkit-flex:0 0 33.33333333%;flex:0 0 33.33333333%;max-width:33.33333333%}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-col-5{-webkit-box-flex:0;-webkit-flex:0 0 41.66666667%;flex:0 0 41.66666667%;max-width:41.66666667%}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-col-6{-webkit-box-flex:0;-webkit-flex:0 0 50%;flex:0 0 50%;max-width:50%}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-col-7{-webkit-box-flex:0;-webkit-flex:0 0 58.33333333%;flex:0 0 58.33333333%;max-width:58.33333333%}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-col-8{-webkit-box-flex:0;-webkit-flex:0 0 66.66666667%;flex:0 0 66.66666667%;max-width:66.66666667%}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-col-9{-webkit-box-flex:0;-webkit-flex:0 0 75%;flex:0 0 75%;max-width:75%}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-col-10{-webkit-box-flex:0;-webkit-flex:0 0 83.33333333%;flex:0 0 83.33333333%;max-width:83.33333333%}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-col-11{-webkit-box-flex:0;-webkit-flex:0 0 91.66666667%;flex:0 0 91.66666667%;max-width:91.66666667%}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-col-12{-webkit-box-flex:0;-webkit-flex:0 0 100%;flex:0 0 100%;max-width:100%}@media (max-width:991px){#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-col-sm-1{-webkit-box-flex:0;-webkit-flex:0 0 8.33333333%;flex:0 0 8.33333333%;max-width:8.33333333%}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-col-sm-2{-webkit-box-flex:0;-webkit-flex:0 0 16.66666667%;flex:0 0 16.66666667%;max-width:16.66666667%}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-col-sm-3{-webkit-box-flex:0;-webkit-flex:0 0 25%;flex:0 0 25%;max-width:25%}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-col-sm-4{-webkit-box-flex:0;-webkit-flex:0 0 33.33333333%;flex:0 0 33.33333333%;max-width:33.33333333%}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-col-sm-5{-webkit-box-flex:0;-webkit-flex:0 0 41.66666667%;flex:0 0 41.66666667%;max-width:41.66666667%}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-col-sm-6{-webkit-box-flex:0;-webkit-flex:0 0 50%;flex:0 0 50%;max-width:50%}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-col-sm-7{-webkit-box-flex:0;-webkit-flex:0 0 58.33333333%;flex:0 0 58.33333333%;max-width:58.33333333%}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-col-sm-8{-webkit-box-flex:0;-webkit-flex:0 0 66.66666667%;flex:0 0 66.66666667%;max-width:66.66666667%}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-col-sm-9{-webkit-box-flex:0;-webkit-flex:0 0 75%;flex:0 0 75%;max-width:75%}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-col-sm-10{-webkit-box-flex:0;-webkit-flex:0 0 83.33333333%;flex:0 0 83.33333333%;max-width:83.33333333%}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-col-sm-11{-webkit-box-flex:0;-webkit-flex:0 0 91.66666667%;flex:0 0 91.66666667%;max-width:91.66666667%}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-col-sm-12{-webkit-box-flex:0;-webkit-flex:0 0 100%;flex:0 0 100%;max-width:100%}}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-headline{font-weight:700;margin-top:1.5em;margin-bottom:.75em}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel h1.typo3-adminPanel-headline{font-weight:400;font-size:1.75em}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel h2.typo3-adminPanel-headline{font-weight:400;font-size:1.5em}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel h3.typo3-adminPanel-headline{font-size:1.35em}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel h4.typo3-adminPanel-headline{font-size:1.25em}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-table-overflow{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #e0e0e0;box-shadow:0 0 1px rgba(0,0,0,.15)}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-table-overflow .typo3-adminPanel-table{border:none}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-table{width:100%;max-width:100%;background-color:#fff;display:table;border-collapse:separate;border-spacing:0;border:1px solid #e0e0e0}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-table thead tr{background-color:#e0e0e0}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-table thead td,#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-table thead th{border-top:none}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-table th{font-weight:700;text-align:inherit}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-table th>span{font-weight:700}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-table tr{font-family:inherit}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-table td,#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-table th{padding:.75em;vertical-align:top;border-top:1px solid #dee2e6}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-table-debug tbody{font-family:monospace}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-table-debug tbody *{font-family:inherit}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-table-debug tbody td{word-wrap:break-word}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-table-cell-key{width:19%}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-table-cell-nowrap{white-space:nowrap}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-card-group{display:-webkit-box;display:-webkit-flex;display:flex;margin:-5px;margin-bottom:1em;-webkit-flex-wrap:wrap;flex-wrap:wrap}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-card-group .typo3-adminPanel-card{margin:5px;-webkit-box-flex:1;-webkit-flex-grow:1;flex-grow:1;-webkit-flex-shrink:0;flex-shrink:0;max-width:100%}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-card{background-color:#fff;margin-bottom:1em;box-shadow:0 0 1px rgba(0,0,0,.15)}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-card-body>:first-child,#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-card-header>:first-child{margin-top:0}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-card-body>:last-child,#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-card-header>:last-child{margin-bottom:0}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-card-header{display:-webkit-box;display:-webkit-flex;display:flex;-webkit-box-align:center;-webkit-align-items:center;align-items:center;padding:20px;padding-bottom:0}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-card-header-headline{display:-webkit-box;display:-webkit-flex;display:flex;-webkit-box-align:center;-webkit-align-items:center;align-items:center}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-card-header-icon{position:relative;height:1em;width:1em;opacity:.75}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-card-header-icon .icon{position:absolute;top:50%;left:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-card-header-text{padding-left:.5em;font-size:1.25em}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-card-body{padding:20px}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-dump{font-family:monospace;word-wrap:break-word;white-space:pre-wrap;position:relative;z-index:99999;word-break:break-all}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-dump-string{color:#75a75a}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-dump-string:after,#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-dump-string:before{color:#bf6500;content:'"'}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-dump-float,#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-dump-integer{color:#538bb3}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-form-group{display:block;margin:1.5em 0}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-form-group-checkbox+.typo3-adminPanel-form-group-checkbox{margin-top:-.5em}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-form-checkbox{padding-left:1.75em}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-form-checkbox-label{position:relative;cursor:pointer}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-form-checkbox-label:before{position:absolute;top:0;left:-1.75em;display:block;width:1.25em;height:1.25em;pointer-events:none;content:'';-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:#dadada;border-radius:2px}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-form-checkbox-label:after{position:absolute;top:0;left:-1.75em;display:block;width:1.25em;height:1.25em;content:'';background-repeat:no-repeat;background-position:center center;background-size:50% 50%}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-form-checkbox-input{display:none}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-form-checkbox-input:checked+.typo3-adminPanel-form-checkbox-label:before{background-color:#629755}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-form-checkbox-input:checked+.typo3-adminPanel-form-checkbox-label:after{background-image:url("data:image/svg+xml;charset=utf8, <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'><path fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/></svg>")}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-form-select .typo3-adminPanel-form-select-label{margin-bottom:.5em;display:block}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-form-select .typo3-adminPanel-form-select-input{padding:.75em 3em .75em 1.25em;display:block;border-radius:2px;border:1px solid #dadada;background:#fff url("data:image/svg+xml;charset=utf8, <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'><path fill='#333' d='M2 0L0 2h4zm0 5L0 3h4z'/></svg>") no-repeat right .75em center;background-size:8px 10px;-webkit-appearance:none;-moz-appearance:none;appearance:none}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-form-select .typo3-adminPanel-form-select-input:focus,#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-form-select .typo3-adminPanel-form-select-input:hover{border:1px solid #cacaca}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-form-datetime .typo3-adminPanel-form-datetime-label{margin-bottom:.5em;display:block}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-form-datetime .typo3-adminPanel-form-datetime-input-group{margin:-5px;display:-webkit-box;display:-webkit-flex;display:flex;-webkit-flex-wrap:wrap;flex-wrap:wrap}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-form-datetime .typo3-adminPanel-form-datetime-input{-webkit-box-flex:1;-webkit-flex-grow:1;flex-grow:1;-webkit-flex-shrink:0;flex-shrink:0;margin:5px;display:block;padding:.75em 1.25em;border-radius:2px;border:1px solid #dadada;background-color:#fff}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-form-datetime .typo3-adminPanel-form-datetime-input:focus,#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-form-datetime .typo3-adminPanel-form-datetime-input:hover{border:1px solid #cacaca}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-btn{position:relative;cursor:pointer;color:inherit;text-decoration:none;padding:.75em 1.25em;display:inline-block;background-color:rgba(0,0,0,.1);border:1px solid #dadada;border-radius:2px}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-btn:focus,#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-btn:hover{z-index:1;background-color:rgba(0,0,0,.15);border:1px solid #cacaca}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-btn-primary{color:#fff;background-color:#538bb3;border:1px solid #417092}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-btn-primary:focus,#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-btn-primary:hover{background-color:#6597bb;border:1px solid #396381}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-btn-group:after{content:'';display:table;clear:both}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-btn-group .typo3-adminPanel-btn{border-radius:0;float:left}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-btn-group .typo3-adminPanel-btn:first-child{border-radius:2px 0 0 2px}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-btn-group .typo3-adminPanel-btn:last-child{border-radius:0 2px 2px 0}#TSFE_ADMIN_PANEL_FORM.typo3-kidjls9dksoje.typo3-adminPanel .typo3-adminPanel-btn-group .typo3-adminPanel-btn+.typo3-adminPanel-btn{margin-left:-1px}
\ No newline at end of file
index bac2194..e62f974 100644 (file)
@@ -1,10 +1,9 @@
 function sendAdminPanelForm(event) {
   event.preventDefault();
-  this.innerText = 'Loading...';
   var typo3AdminPanel = document.querySelector('[data-typo3-role=typo3-adminPanel]');
-  var formData = new FormData(typo3AdminPanel.querySelector('form'));
+  var formData = new FormData(typo3AdminPanel);
   var request = new XMLHttpRequest();
-  request.open('POST', typo3AdminPanel.dataset.typo3AjaxUrl);
+  request.open("POST", typo3AdminPanel.dataset.typo3AjaxUrl);
   request.send(formData);
   request.onload = function () {
     location.reload();
@@ -13,14 +12,66 @@ function sendAdminPanelForm(event) {
 
 function toggleAdminPanelState() {
   var request = new XMLHttpRequest();
-  request.open('GET', this.dataset.typo3AjaxUrl);
+  request.open("GET", this.dataset.typo3AjaxUrl);
   request.send();
   request.onload = function () {
     location.reload();
   };
 }
 
+function renderBackdrop() {
+  var adminPanel = document.querySelector('#TSFE_ADMIN_PANEL_FORM');
+  var backdrop = document.createElement('div');
+  backdrop.classList.add('typo3-adminPanel-backdrop');
+  adminPanel.appendChild(backdrop);
+  addBackdropListener();
+}
+
+function removeBackdrop() {
+  var backdrop = document.querySelector('.typo3-adminPanel-backdrop');
+  if (backdrop !== null) {
+    backdrop.remove();
+  }
+}
+
+function addBackdropListener() {
+  var allBackdrops = Array.from(document.querySelectorAll('.typo3-adminPanel-backdrop'));
+  allBackdrops.forEach(function (elm) {
+    elm.addEventListener('click', function () {
+      removeBackdrop();
+      var allModules = Array.from(document.querySelectorAll('[data-typo3-role=typo3-adminPanel-module-trigger]'));
+      allModules.forEach(function (innerElm) {
+        innerElm.closest('.typo3-adminPanel-module').classList.remove('typo3-adminPanel-module-active');
+      });
+    });
+  });
+}
+
+function addModuleListener(allModules) {
+  allModules.forEach(function (elm) {
+    elm.addEventListener('click', function () {
+      var parent = this.closest('.typo3-adminPanel-module');
+      if (parent.classList.contains('typo3-adminPanel-module-active')) {
+        removeBackdrop();
+        parent.classList.remove('typo3-adminPanel-module-active');
+      } else {
+        allModules.forEach(function (innerElm) {
+          removeBackdrop();
+          innerElm.closest('.typo3-adminPanel-module').classList.remove('typo3-adminPanel-module-active');
+        });
+        renderBackdrop();
+        parent.classList.add('typo3-adminPanel-module-active');
+      }
+    });
+  });
+}
+
 function initializeAdminPanel() {
+  var allModules = Array.from(document.querySelectorAll('[data-typo3-role=typo3-adminPanel-module-trigger]'));
+  addModuleListener(allModules);
+  initializeTabs();
+
+
   Array.from(document.querySelectorAll('[data-typo3-role=typo3-adminPanel-saveButton]')).forEach(function (elm) {
     elm.addEventListener('click', sendAdminPanelForm);
   });
@@ -28,6 +79,105 @@ function initializeAdminPanel() {
   Array.from(document.querySelectorAll('[data-typo3-role=typo3-adminPanel-trigger]')).forEach(function (trigger) {
     trigger.addEventListener('click', toggleAdminPanelState);
   });
+
+  var popupTriggers = Array.from(document.querySelectorAll('[data-typo3-role=typo3-adminPanel-popup-trigger]'));
+  popupTriggers.forEach(function (elm) {
+    elm.addEventListener('click', function () {
+      if (this.classList.contains('active')) {
+        this.classList.remove('active');
+      } else {
+        popupTriggers.forEach(function (innerElm) {
+          innerElm.classList.remove('active');
+        });
+        this.classList.add('active');
+      }
+    });
+  });
+
+  var panelTriggers = Array.from(document.querySelectorAll('[data-typo3-role=typo3-adminPanel-panel-trigger]'));
+  panelTriggers.forEach(function (elm) {
+    elm.addEventListener('click', function () {
+      var target = this.closest('.typo3-adminPanel-panel');
+      if (target.classList.contains('active')) {
+        target.classList.remove('active');
+      } else {
+        target.classList.add('active');
+      }
+    });
+  });
+
+  var settingsTriggers = Array.from(document.querySelectorAll('[data-typo3-role=typo3-adminPanel-content-settings]'));
+  settingsTriggers.forEach(function (elm) {
+    elm.addEventListener('click', function () {
+      var target = this.closest('.typo3-adminPanel-content').querySelector('.typo3-adminPanel-content-settings');
+      if (target.classList.contains('typo3-adminPanel-content-settings-active')) {
+        target.classList.remove('typo3-adminPanel-content-settings-active');
+      } else {
+        target.classList.add('typo3-adminPanel-content-settings-active');
+      }
+    });
+  });
+
+  var moduleClose = Array.from(document.querySelectorAll('[data-typo3-role=typo3-adminPanel-content-close]'));
+  moduleClose.forEach(function (elm) {
+    elm.addEventListener('click', function () {
+      allModules.forEach(function (innerElm) {
+        innerElm.closest('.typo3-adminPanel-module').classList.remove('typo3-adminPanel-module-active');
+      });
+      removeBackdrop();
+    });
+  });
+
+  var dataFields = Array.from(document.querySelectorAll('.typo3-adminPanel-table th, .typo3-adminPanel-table td'));
+  dataFields.forEach(function (elm) {
+    elm.addEventListener('click', function () {
+      elm.focus();
+      // elm.select();
+
+      try {
+        var successful = document.execCommand('copy');
+        var msg = successful ? 'successful' : 'unsuccessful';
+        console.log('Copying text command was ' + msg);
+      } catch (err) {
+        console.log('Oops, unable to copy');
+      }
+    });
+  });
+
+  addBackdropListener();
+}
+
+/**
+ * Tabs
+ */
+function initializeTabs() {
+  var tabs = document.querySelectorAll('[data-typo3-role=typo3-adminPanel-content-tab]');
+
+  function switchTab(event) {
+    event.preventDefault();
+
+    var activeTabClass = 'typo3-adminPanel-content-header-item-active';
+    var activePaneClass = 'typo3-adminPanel-content-panes-item-active';
+    var currentTab = event.currentTarget;
+    var currentContent = currentTab.closest('[data-typo3-role=typo3-adminPanel-content]');
+    var contentTabs = currentContent.querySelectorAll('[data-typo3-role=typo3-adminPanel-content-tab]');
+    var contentPanes = currentContent.querySelectorAll('[data-typo3-role=typo3-adminPanel-content-pane]');
+
+    for (var i = 0; i < contentTabs.length; i++) {
+      contentTabs[i].classList.remove(activeTabClass);
+    }
+    currentTab.classList.add(activeTabClass);
+    for (var j = 0; j < contentPanes.length; j++) {
+      contentPanes[j].classList.remove(activePaneClass);
+    }
+
+    var activePane = document.querySelector('[data-typo3-tab-id=' + currentTab.dataset.typo3TabTarget + ']');
+    activePane.classList.add(activePaneClass);
+  }
+
+  for (var i = 0; i < tabs.length; i++) {
+    tabs[i].addEventListener("click", switchTab)
+  }
 }
 
 window.addEventListener('load', initializeAdminPanel, false);
diff --git a/typo3/sysext/adminpanel/Resources/Public/JavaScript/Modules/Cache.js b/typo3/sysext/adminpanel/Resources/Public/JavaScript/Modules/Cache.js
new file mode 100644 (file)
index 0000000..28a00b6
--- /dev/null
@@ -0,0 +1,19 @@
+function initializeCacheModule() {
+       var buttons = Array.from(document.querySelectorAll('[data-typo3-role=clearCacheButton]'));
+
+       buttons.forEach(function (elem) {
+               elem.addEventListener('click', clearCache);
+       });
+}
+
+function clearCache() {
+       var url = this.dataset.typo3AjaxUrl;
+       var request = new XMLHttpRequest();
+       request.open("GET", url);
+       request.send();
+       request.onload = function () {
+               location.reload();
+       };
+}
+
+window.addEventListener('load', initializeCacheModule, false);
diff --git a/typo3/sysext/adminpanel/Resources/Public/JavaScript/Modules/Edit.js b/typo3/sysext/adminpanel/Resources/Public/JavaScript/Modules/Edit.js
new file mode 100644 (file)
index 0000000..0fee2e8
--- /dev/null
@@ -0,0 +1,24 @@
+function editModuleOnClickHandler(event) {
+       event.preventDefault();
+       var element = event.target;
+       if (parent.opener && parent.opener.top) {
+               parent.opener.top.fsMod.recentIds['web'] = element.getAttribute('data-pageUid');
+               if (parent.opener.top && parent.opener.top.nav_frame && parent.opener.top.nav_frame.refresh_nav) {
+                       parent.opener.top.nav_frame.refresh_nav();
+               }
+               parent.opener.top.goToModule(element.getAttribute('data-pageModule'));
+               parent.opener.top.focus();
+       } else {
+               var vHWin = window.open(element.getAttribute('data-backendScript'), element.getAttribute('data-t3BeSitenameMd5'));
+               vHWin.focus();
+       }
+       return false;
+}
+
+function initializeEditModule() {
+       var editModuleBtnOpenBackend = document.querySelector('.typo3-adminPanel-btn-openBackend');
+       editModuleBtnOpenBackend.addEventListener('click', editModuleOnClickHandler);
+}
+
+
+window.addEventListener('load', initializeEditModule, false);
diff --git a/typo3/sysext/adminpanel/Resources/Public/JavaScript/Modules/Edit/OpenBackendHandler.js b/typo3/sysext/adminpanel/Resources/Public/JavaScript/Modules/Edit/OpenBackendHandler.js
deleted file mode 100644 (file)
index 9ece5d0..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-const editModuleBtnOpenBackend = document.querySelector('.typo3-adminPanel-btn-openBackend');
-editModuleBtnOpenBackend.addEventListener('click', editModuleOnClickHandler);
-
-function editModuleOnClickHandler(event) {
-  event.preventDefault();
-  const element = event.target;
-  if (parent.opener && parent.opener.top) {
-    parent.opener.top.fsMod.recentIds['web'] = element.getAttribute('data-pageUid');
-    if (parent.opener.top && parent.opener.top.nav_frame && parent.opener.top.nav_frame.refresh_nav) {
-      parent.opener.top.nav_frame.refresh_nav();
-    }
-    parent.opener.top.goToModule(element.getAttribute('data-pageModule'));
-    parent.opener.top.focus();
-  } else {
-    const vHWin = window.open(element.getAttribute('data-backendScript'), element.getAttribute('data-t3BeSitenameMd5'));
-    vHWin.focus();
-  }
-  return false;
-}
diff --git a/typo3/sysext/adminpanel/Resources/Public/JavaScript/Modules/Preview.js b/typo3/sysext/adminpanel/Resources/Public/JavaScript/Modules/Preview.js
new file mode 100644 (file)
index 0000000..4add742
--- /dev/null
@@ -0,0 +1,35 @@
+
+function initializePreviewModule() {
+       var dateField = document.getElementById('preview_simulateDate-date-hr');
+       var timeField = document.getElementById('preview_simulateDate-time-hr');
+       var targetField = document.getElementById(dateField.dataset.target);
+       if (targetField.value) {
+               var cd = new Date(targetField.value);
+               document.getElementById('preview_simulateDate-date-hr').value = cd.getFullYear() + "-" + ((cd.getMonth()+1) < 10 ? '0' : '') + (cd.getMonth()+1) + "-" + (cd.getDate() < 10 ? '0' : '') + cd.getDate();
+               document.getElementById('preview_simulateDate-time-hr').value = (cd.getHours() < 10 ? '0' : '') + cd.getHours() + ":" + (cd.getMinutes() < 10 ? '0' : '') + cd.getMinutes();
+       }
+
+       var updateDateField = function () {
+               var dateVal = document.getElementById('preview_simulateDate-date-hr').value;
+               var timeVal = document.getElementById('preview_simulateDate-time-hr').value;
+               if (!dateVal && timeVal) {
+                       var tempDate = new Date();
+                       dateVal = tempDate.getDate() + "-" + tempDate.getMonth() + "-" + tempDate.getFullYear();
+               }
+               if (dateVal && !timeVal) {
+                       timeVal =  "00:00";
+               }
+
+               if(!dateVal && !timeVal) {
+                       targetField.value = "";
+               } else {
+                       var stringDate = dateVal + " " + timeVal;
+                       var date = new Date(stringDate);
+                       targetField.value = date.toISOString();
+               }
+       };
+       dateField.addEventListener('change', updateDateField);
+       timeField.addEventListener('change', updateDateField);
+}
+
+window.addEventListener('load', initializePreviewModule, false);
diff --git a/typo3/sysext/adminpanel/Resources/Public/JavaScript/Modules/TsDebug.js b/typo3/sysext/adminpanel/Resources/Public/JavaScript/Modules/TsDebug.js
new file mode 100644 (file)
index 0000000..e69de29
index 6c2eaa7..95ffae4 100644 (file)
@@ -18,12 +18,12 @@ namespace TYPO3\CMS\Adminpanel\Tests\Unit\Middleware;
 use Prophecy\Argument;
 use Prophecy\Prophecy\ObjectProphecy;
 use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
 use Psr\Http\Server\RequestHandlerInterface;
 use TYPO3\CMS\Adminpanel\Controller\MainController;
 use TYPO3\CMS\Adminpanel\Middleware\AdminPanelInitiator;
 use TYPO3\CMS\Adminpanel\View\AdminPanelView;
 use TYPO3\CMS\Backend\FrontendBackendUserAuthentication;
-use TYPO3\CMS\Core\Http\ServerRequest;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
@@ -67,7 +67,7 @@ class AdminPanelInitiatorTest extends UnitTestCase
         GeneralUtility::setSingletonInstance(MainController::class, $controller->reveal());
         GeneralUtility::addInstance(AdminPanelView::class, $this->prophesize(AdminPanelView::class)->reveal());
         $handler = $this->prophesizeHandler();
-        $request = $this->prophesize(ServerRequest::class);
+        $request = $this->prophesize(ServerRequestInterface::class);
         // Act
         $adminPanelInitiator = new AdminPanelInitiator();
         $adminPanelInitiator->process(
@@ -132,7 +132,7 @@ class AdminPanelInitiatorTest extends UnitTestCase
         $controller = $this->prophesize(MainController::class);
         GeneralUtility::setSingletonInstance(MainController::class, $controller->reveal());
         $handler = $this->prophesizeHandler();
-        $request = $this->prophesize(ServerRequest::class);
+        $request = $this->prophesize(ServerRequestInterface::class);
         // Act
         $adminPanelInitiator = new AdminPanelInitiator();
         $adminPanelInitiator->process(
diff --git a/typo3/sysext/adminpanel/Tests/Unit/Modules/PreviewModuleTest.php b/typo3/sysext/adminpanel/Tests/Unit/Modules/PreviewModuleTest.php
new file mode 100644 (file)
index 0000000..012c607
--- /dev/null
@@ -0,0 +1,59 @@
+<?php
+declare(strict_types = 1);
+
+namespace TYPO3\CMS\Adminpanel\Tests\Unit\Modules;
+
+use Prophecy\Argument;
+use Psr\Http\Message\ServerRequestInterface;
+use TYPO3\CMS\Adminpanel\Modules\PreviewModule;
+use TYPO3\CMS\Adminpanel\Service\ConfigurationService;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
+use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
+
+class PreviewModuleTest extends UnitTestCase
+{
+    public function simulateDateDataProvider()
+    {
+        return [
+            'datetime' => [
+                '2018-01-01T12:00:15Z',
+                (int)(new \DateTime('2018-01-01 12:00:15 UTC'))->getTimestamp(),
+                (new \DateTime('2018-01-01 12:00:00 UTC'))->getTimestamp(),
+            ],
+            'timestamp' => [
+                (new \DateTime('2018-01-01 12:00:15 UTC'))->getTimestamp(),
+                (int)(new \DateTime('2018-01-01 12:00:15 UTC'))->getTimestamp(),
+                (int)(new \DateTime('2018-01-01 12:00:00 UTC'))->getTimestamp(),
+            ],
+
+        ];
+    }
+
+    /**
+     * @test
+     * @dataProvider simulateDateDataProvider
+     * @param string $dateToSimulate
+     * @param int $expectedExecTime
+     * @param int $expectedAccessTime
+     */
+    public function initializeFrontendPreviewSetsDateForSimulation(string $dateToSimulate, int $expectedExecTime, int $expectedAccessTime): void
+    {
+        $this->resetSingletonInstances = true;
+        $request = $this->prophesize(ServerRequestInterface::class);
+        $tsfe = $this->prophesize(TypoScriptFrontendController::class);
+        $GLOBALS['TSFE'] = $tsfe->reveal();
+        $configurationService = $this->prophesize(ConfigurationService::class);
+        $configurationService->getMainConfiguration()->willReturn([]);
+        $configurationService->getConfigurationOption('preview', 'simulateDate')->willReturn($dateToSimulate);
+        $configurationService->getConfigurationOption('preview', Argument::any())->willReturn('');
+
+        GeneralUtility::setSingletonInstance(ConfigurationService::class, $configurationService->reveal());
+
+        $previewModule = new PreviewModule();
+        $previewModule->initializeModule($request->reveal());
+
+        self::assertSame($GLOBALS['SIM_EXEC_TIME'], $expectedExecTime, 'EXEC_TIME');
+        self::assertSame($GLOBALS['SIM_ACCESS_TIME'], $expectedAccessTime, 'ACCESS_TIME');
+    }
+}
index dd44bc7..8b8a79e 100644 (file)
@@ -1,7 +1,8 @@
 <?php
 defined('TYPO3_MODE') or die();
 
-$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_fe.php']['hook_eofe'][] = \TYPO3\CMS\Adminpanel\Hooks\RenderHook::class . '->renderAdminPanel';
+$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_fe.php']['hook_eofe'][]
+    = \TYPO3\CMS\Adminpanel\Hooks\RenderHook::class . '->renderAdminPanel';
 
 $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules'] = [
     'preview' => [
@@ -19,9 +20,28 @@ $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules'] = [
     'tsdebug' => [
         'module' => \TYPO3\CMS\Adminpanel\Modules\TsDebugModule::class,
         'after' => ['edit'],
+        'submodules' => [
+            'ts-waterfall' => [
+                'module' => \TYPO3\CMS\Adminpanel\Modules\TsDebug\TypoScriptWaterfall::class
+            ]
+        ]
     ],
     'info' => [
         'module' => \TYPO3\CMS\Adminpanel\Modules\InfoModule::class,
         'after' => ['tsdebug'],
+        'submodules' => [
+            'general' => [
+                'module' => \TYPO3\CMS\Adminpanel\Modules\Info\GeneralInformation::class
+            ],
+            'request' => [
+                'module' => \TYPO3\CMS\Adminpanel\Modules\Info\RequestInformation::class
+            ],
+            'phpinfo' => [
+                'module' => \TYPO3\CMS\Adminpanel\Modules\Info\PhpInformation::class
+            ],
+        ]
     ],
 ];
+
+$GLOBALS['TYPO3_CONF_VARS']['FE']['eID_include']['adminPanel_save']
+    = \TYPO3\CMS\Adminpanel\Controller\AjaxController::class . '::saveDataAction';
index 25981ec..e64f984 100644 (file)
@@ -375,10 +375,9 @@ class TimeTracker implements SingletonInterface
         $keyLgd = $this->printConf['keyLgd'];
         $c = 0;
         foreach ($this->tsStackLog as $uniqueId => $data) {
+            $logRowClass = '';
             if ($this->highlightLongerThan && (int)$data['owntime'] > (int)$this->highlightLongerThan) {
                 $logRowClass = 'typo3-adminPanel-logRow-highlight';
-            } else {
-                $logRowClass = $c % 2 ? 'line-odd' : 'line-even';
             }
             $item = '';
             // If first...
@@ -410,7 +409,7 @@ class TimeTracker implements SingletonInterface
             $theLabel = GeneralUtility::fixed_lgd_cs($theLabel, -$keyLgd);
             $theLabel = $data['stackPointer'] ? '<span class="stackPointer">' . $theLabel . '</span>' : $theLabel;
             $keyLabel = $theLabel . $keyLabel;
-            $item .= '<td class="typo3-adminPanel-table-cell-nowrap ' . $logRowClass . '">' . ($flag_tree ? $data['icons'] : '') . $this->fw($keyLabel) . '</td>';
+            $item .= '<th scope="row" class="typo3-adminPanel-table-cell-key ' . $logRowClass . '">' . ($flag_tree ? $data['icons'] : '') . $this->fw($keyLabel) . '</th>';
             // Key value:
             $keyValue = $data['value'];
             $item .= '<td class="' . $logRowClass . ' typo3-adminPanel-tsLogTime">' . $this->fw(htmlspecialchars($keyValue)) . '</td>';
@@ -448,7 +447,7 @@ class TimeTracker implements SingletonInterface
             $out .= '<tr>' . $item . '</tr>';
             $c++;
         }
-        $out = '<div class="typo3-adminPanel-table-overflow"><table class="typo3-adminPanel-table">' . $out . '</table></div>';
+        $out = '<div class="typo3-adminPanel-table-overflow"><table class="typo3-adminPanel-table typo3-adminPanel-table-debug">' . $out . '</table></div>';
         return $out;
     }
 
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Deprecation-84584-AdminPanelViewIsAdminModuleEnabledAndExt_makeToolbarDeprecated.rst b/typo3/sysext/core/Documentation/Changelog/master/Deprecation-84584-AdminPanelViewIsAdminModuleEnabledAndExt_makeToolbarDeprecated.rst
new file mode 100644 (file)
index 0000000..f7ca620
--- /dev/null
@@ -0,0 +1,41 @@
+.. include:: ../../Includes.txt
+
+=========================================================================================
+Deprecation: #84584 - AdminPanelView: isAdminModuleEnabled and ext_makeToolbar deprecated
+=========================================================================================
+
+See :issue:`84584`
+
+Description
+===========
+
+Due to the complete refactoring of the admin panel, the following methods have been deprecated:
+
+- `\TYPO3\CMS\Adminpanel\View\AdminPanelView::isAdminModuleEnabled`
+- `\TYPO3\CMS\Adminpanel\View\AdminPanelView::ext_makeToolBar`
+
+
+Impact
+======
+
+Calling either one of the methods results in a deprecation warning.
+
+
+Affected Installations
+======================
+
+Installations calling either of the methods.
+
+
+Migration
+=========
+
+Migrate `\TYPO3\CMS\Adminpanel\View\AdminPanelView::isAdminModuleEnabled`:
+
+- Refactor your admin panel modules to the new API (using AbstractModule / AdminPanelModuleInterface) and check via "Module->isEnabled()"
+- When using this with existing admin panel modules call "isEnabled" on the new module instance instead
+
+Migrate `\TYPO3\CMS\Adminpanel\View\AdminPanelView::ext_makeToolBar`:
+- When building your custom edit toolbars, build them yourself matching your templates and styles - you can use `\TYPO3\CMS\Adminpanel\Service\EditToolbarService::createToolbar` as an inspiration on how to do so.
+
+.. index:: Frontend, PHP-API, FullyScanned, ext:adminpanel
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-84584-Re-DesignTheAdminPanel.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-84584-Re-DesignTheAdminPanel.rst
new file mode 100644 (file)
index 0000000..515c96f
--- /dev/null
@@ -0,0 +1,111 @@
+.. include:: ../../Includes.txt
+
+===========================================
+Feature: #84584 - Re-Design the admin panel
+===========================================
+
+See :issue:`84584`
+
+Description
+===========
+
+The admin panel got a complete overhaul regarding its design as well as the underlying code and extensibility.
+
+The panel is now structurally separated in modules and submodules. Each module is completely responsible for its own rendering, collection of information, settings and behaviour - dependencies to other parts of the core were resolved. Extension authors can now write their own modules or add submodules to existing modules.
+
+An admin panel module commonly has
+- an icon, identifier, a short info and a label
+- initializeModule and onSubmit methods for initialization (done early in the TYPO3 Request) and reacting to changes (onSubmit is executed when the settings are updated)
+- settings that influence page rendering or page display
+- methods to provide custom CSS and JavaScript files
+- submodules
+
+An admin panel submodule has
+- an identifier and a label
+- initializeModule and onSubmit methods for initialization (done early in the TYPO3 Request) and reacting to changes (onSubmit is executed when the settings are updated)
+- module content (for example the Info submodules display information about the current page or server configuration)
+- settings influencing their module content (for example the TypoScript Time / Rendering sub module has settings that influence whether to display messages or not)
+
+UI wise the following changes were done
+- Ajax is used to save configuration options, so only a single reload is triggered even if multiple settings changed.
+- Settings influencing page rendering should be grouped together
+- Most important info should be available at a glance with possibilities to show extended information
+- Complete design overhaul
+
+
+Impact
+======
+
+The new admin panel provides a better look and feel as well as more convenient access to information and more flexible extensibility. For backwards compatibility enabling and disabling modules or options for editors is still possible via User TSConfig.
+
+Creating additional modules
+===========================
+
+To create your own admin panel module, create a new PHP class extending `\TYPO3\CMS\Adminpanel\Modules\AbstractModule`.
+
+Implement at least the following methods:
+- `getIdentifier` - A unique identifier for your module (for example `mynamespace_modulename`)
+- `getIconIdentifier` - An icon identifier (resolved via the icon API, make sure to use a registered icon here)
+- `getLabel` - Speaking label for the module - you can access language files via `$this->getLanguageService()`
+- `getShortInfo` - Displayed next to the module label, may contain aggregated infos (such as `Total Parse Time: 200ms`)
+
+Register your module by adding the following in your `ext_localconf.php`::
+
+    $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']['mynamespace_modulename'] => [
+        'module' => \Your\Namespace\Adminpanel\Modules\YourModule::class,
+        'before' => ['cache'],
+    ],
+
+via `before` or `after` you can influence where your module will be displayed in the module menu by referencing the
+identifier / array key of other modules.
+
+Modules themselves do provide settings for the page rendering or global actions (like preview settings, clearing caches or
+adding action buttons for editing the page) but do not provide further content. If you want to display additional content
+in the admin panel (like rendering times or backtraces or whatever you wish), you have to add a submodule to your main
+module.
+
+To provide settings in a module, implement the method `getSettings`, which has to return rendered HTML form elements
+(but without the form tag), ready to be used in the admin panel main form.
+
+Adding a sub-module
+===================
+
+First of all: As soon as a module has a submodule it will be displayed in the main admin panel. Modules without submodules
+may only provide settings and aren't displayed in the module bar but only in the settings overview.
+
+Adding a submodule is similar to adding a module. First, create a new class that extends `AbstractSubModule`. Implement
+at least the following methods:
+
+- `getIdentifier` - A unique identifier for your sub module (for example `submodulename`)
+- `getLabel` - Speaking label for the module - you can access language files via `$this->getLanguageService()`
+- `getContent` - The rendered HTML content for your module
+
+Register your sub module by adding the following in your `ext_localconf.php`::
+
+    $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']['mynamespace_modulename']['submodules']['submodulename'] => [
+      'module' => \Your\Namespace\Adminpanel\Modules\YourModule\Submodule::class
+    ]
+
+where `mynamespace_modulename` references the main module where you want to add your submodule, and `submodulename` is the
+identifier of your sub module.
+
+This way, you can also register new custom sub modules to existing main modules.
+
+Advanced Usage
+--------------
+
+You can also implement the logic completely on your own not using the `AbstractModule` / `AbstractSubModule` by implementing
+the corresponding interfaces `AdminPanelModuleInterface` and `AdminPanelSubModuleInterface`.
+
+Examples
+========
+
+You can find examples for main and sub modules and their registration in the admin panel extension. Short ones for a quick
+look are:
+
+- `adminpanel/Classes/Modules/Info/PhpInformation.php` (Submodule)
+- `adminpanel/Classes/Modules/InfoModule.php` (Main module, serves as submodule wrapper only)
+- `adminpanel/Classes/Modules/EditModule.php` (Main module, custom rendering settings)
+
+
+.. index:: Frontend, PHP-API, ext:adminpanel
index 4b88e95..b11b21b 100644 (file)
@@ -2494,4 +2494,18 @@ return [
             'Deprecation-85666-TypoScriptFrontendController-initTemplate.rst',
         ],
     ],
+    'TYPO3\CMS\Adminpanel\View\AdminPanelView->isAdminModuleEnabled' => [
+        'numberOfMandatoryArguments' => 1,
+        'maximumNumberOfArguments' => 1,
+        'restFiles' => [
+            'Deprecation-84584-AdminPanelViewIsAdminModuleEnabledAndExt_makeToolbarDeprecated.rst',
+        ],
+    ],
+    'TYPO3\CMS\Adminpanel\View\AdminPanelView->ext_makeToolBar' => [
+        'numberOfMandatoryArguments' => 0,
+        'maximumNumberOfArguments' => 0,
+        'restFiles' => [
+            'Deprecation-84584-AdminPanelViewIsAdminModuleEnabledAndExt_makeToolbarDeprecated.rst',
+        ],
+    ],
 ];