From d644dbc1a43797734e485d2229c5a112b7fd1d9a Mon Sep 17 00:00:00 2001 From: Benjamin Kott <benjamin.kott@outlook.com> Date: Thu, 20 Apr 2023 11:34:38 +0200 Subject: [PATCH] [TASK] Streamline spacings General spacings have been streamlined that are most relevant for CSS declarations that add `margin-bottom` to ensure there is space available to the next element. Headlines h1, h2, and h3 will not add additional space to the top if they are used in a document flow and are not the first element, and have no classes assigned. This provides a visual divider when a new content section is opened while keeping existing styles untouched. There are edge cases where it can be necessary to add the space manually because some additional necessary nesting is in place. For this case, the class `.headline-spaced` was introduced. This class is limited to h1, h2, and h3 and should be used with care. The code styling for <pre> and <code> has been adjusted when `[class*="language-"]` is matching. While we have no automatic syntax highlighting for this kind of area yet, this indicates that a user wants to highlight a section of code. Dropping row and col implementations for inline forms. We are introducing `.form-row` and respective variants to different viewports `.form-row-*` to have more control over spacing for inline forms. Each input element will consume the necessary space it needs and wrap if not enough space is available. The spacing for clearable elements is now applied to `.form-control-clearable`. This allows the spacing adjustments to be present before the JavaScript is invoked. The class will be added through js if not already present on the element. This avoids additional layout shifts. Resolves: #100663 Releases: main Change-Id: If9757d9dc04d9dca83cb1e89c5bbced1b20b5850 Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/78682 Tested-by: Benni Mack <benni@typo3.org> Tested-by: core-ci <typo3@b13.com> Reviewed-by: Andreas Fernandez <a.fernandez@scripting-base.de> Reviewed-by: Benni Mack <benni@typo3.org> Tested-by: Andreas Fernandez <a.fernandez@scripting-base.de> --- Build/Sources/Sass/_minimal.scss | 2 + Build/Sources/Sass/backend.scss | 1 + Build/Sources/Sass/component/_card.scss | 4 +- Build/Sources/Sass/component/_checkbox.scss | 12 +- Build/Sources/Sass/component/_code.scss | 30 +- Build/Sources/Sass/component/_form.scss | 34 +- Build/Sources/Sass/component/_module.scss | 4 - Build/Sources/Sass/component/_note.scss | 6 +- Build/Sources/Sass/component/_pagination.scss | 7 + Build/Sources/Sass/component/_panel.scss | 4 +- Build/Sources/Sass/component/_recordlist.scss | 6 +- .../Sass/component/_recordsearchbox.scss | 2 +- Build/Sources/Sass/component/_resources.scss | 3 +- Build/Sources/Sass/component/_root.scss | 2 +- Build/Sources/Sass/component/_spacer.scss | 13 + .../Sources/Sass/component/_statusreport.scss | 2 +- Build/Sources/Sass/component/_table.scss | 2 +- Build/Sources/Sass/component/_type.scss | 26 ++ Build/Sources/Sass/module/_install.scss | 2 + Build/Sources/Sass/module/_page.scss | 2 +- Build/Sources/Sass/module/_scheduler.scss | 4 - Build/Sources/Sass/typo3/_main_content.scss | 13 - Build/Sources/Sass/typo3/_main_form.scss | 31 +- Build/Sources/Sass/variables/_main.scss | 20 +- .../Sources/TypeScript/backend/form-engine.ts | 4 +- .../field-control/password-generator.ts | 2 +- .../TypeScript/backend/input/clearable.ts | 4 +- Build/Sources/TypeScript/backend/login.ts | 2 +- Build/Sources/TypeScript/belog/backend-log.ts | 4 +- .../install/renderable/clearable.ts | 4 +- .../TypeScript/lowlevel/query-generator.ts | 79 ++-- .../Controller/RecordListController.php | 14 +- .../Classes/Form/Element/DatetimeElement.php | 1 + .../Classes/Form/Element/EmailElement.php | 1 + .../Classes/Form/Element/InputTextElement.php | 1 + .../Classes/Form/Element/LinkElement.php | 1 + .../Classes/Form/Element/NumberElement.php | 1 + .../Classes/Form/Element/PasswordElement.php | 1 + .../Resources/Private/Layouts/Module.html | 4 + .../Private/Partials/About/Logo.html | 9 +- .../Partials/PageLayout/LanguageColumns.html | 4 +- .../Templates/Login/ForgetPasswordForm.html | 2 +- .../Templates/Login/ResetPasswordForm.html | 4 +- .../Templates/Login/UserPassLoginForm.html | 2 +- .../Private/Templates/Page/NewPages.html | 18 +- .../Templates/PageLayout/PageModule.html | 12 +- .../PageLayout/PageModuleNoAccess.html | 12 +- .../Templates/PageTsConfig/Active.html | 106 ++--- .../Templates/PageTsConfig/Includes.html | 84 ++-- .../PageTsConfig/RecordsOverview.html | 12 +- .../Templates/RecordDownloadSettings.html | 79 ++-- .../Private/Templates/RecordList.html | 12 +- .../Templates/SiteConfiguration/Overview.html | 2 +- .../backend/Resources/Public/Css/backend.css | 140 ++++--- .../Public/JavaScript/form-engine.js | 2 +- .../field-control/password-generator.js | 2 +- .../Public/JavaScript/input/clearable.js | 2 +- .../Private/Partials/Content/Filter.html | 28 +- .../Private/Partials/BackendUser/Filter.html | 16 +- .../Partials/BackendUserGroup/Filter.html | 8 +- .../Private/Templates/BackendUser/List.html | 18 +- .../Private/Templates/BackendUser/Show.html | 22 +- .../Templates/BackendUserGroup/List.html | 18 +- .../Private/Templates/Permission/Edit.html | 104 ++++- .../Application/DbCheck/DbCheckModuleCest.php | 2 +- .../RecordList/RecordDownloadCest.php | 6 +- .../Private/Templates/List/Distributions.html | 10 +- .../Private/Templates/List/Index.html | 6 +- .../Resources/Private/Templates/List/Ter.html | 6 +- .../Private/Templates/File/List.html | 5 +- .../Resources/Private/Templates/Export.html | 22 +- .../Resources/Private/Templates/Import.html | 21 +- .../Templates/Administration/Index.html | 8 +- .../Templates/Administration/Statistic.html | 6 +- .../Administration/StatisticDetails.html | 18 +- .../Private/Templates/PageInformation.html | 23 +- .../Private/Templates/TranslationStatus.html | 45 +- .../Environment/ImageProcessing.html | 115 +++--- .../Public/JavaScript/renderable/clearable.js | 2 +- .../Private/Partials/LevelSelector.html | 18 +- .../Private/Templates/Backend/CheckLinks.html | 14 +- .../Private/Templates/Backend/Report.html | 18 +- .../DatabaseIntegrityController.php | 389 +++++++++++------- .../Private/Templates/Configuration.html | 10 +- .../Private/Templates/CustomSearch.html | 21 +- .../Public/JavaScript/query-generator.js | 2 +- .../Templates/Management/Overview.html | 8 +- .../Private/Templates/RecyclerModule.html | 10 +- .../Templates/Management/Overview.html | 26 +- .../Partials/AddEditStartEndFields.html | 4 +- .../Resources/Private/Templates/Main.html | 14 +- .../Private/Partials/ActiveConditions.html | 74 ++-- .../Private/Partials/ActiveOptions.html | 24 +- .../Private/Partials/ActiveTreePanel.html | 2 +- .../Private/Partials/AnalyzerConditions.html | 74 ++-- .../Private/Partials/AnalyzerOptions.html | 4 +- .../Partials/ConstantEditorOptions.html | 6 +- .../Private/Templates/ActiveMain.html | 13 +- .../Resources/Private/Templates/Analyzer.html | 13 +- .../Private/Templates/ConstantEditorMain.html | 12 +- .../Private/Templates/InfoModifyMain.html | 16 +- .../Templates/Management/Overview.html | 8 +- .../Private/Partials/WorkingTable.html | 12 +- 103 files changed, 1240 insertions(+), 920 deletions(-) create mode 100644 Build/Sources/Sass/component/_pagination.scss create mode 100644 Build/Sources/Sass/component/_spacer.scss create mode 100644 Build/Sources/Sass/component/_type.scss diff --git a/Build/Sources/Sass/_minimal.scss b/Build/Sources/Sass/_minimal.scss index 26fc2eb13e93..bde433fb9dd7 100644 --- a/Build/Sources/Sass/_minimal.scss +++ b/Build/Sources/Sass/_minimal.scss @@ -80,6 +80,8 @@ // Components // @import "component/root"; +@import "component/type"; +@import "component/spacer"; @import "component/alert"; @import "component/autocomplete"; @import "component/badges"; diff --git a/Build/Sources/Sass/backend.scss b/Build/Sources/Sass/backend.scss index 0afb22559ee4..400f5260603e 100644 --- a/Build/Sources/Sass/backend.scss +++ b/Build/Sources/Sass/backend.scss @@ -59,6 +59,7 @@ @import "component/recordsearchbox"; @import "component/treelist"; @import "component/indent"; +@import "component/pagination"; // // Elements diff --git a/Build/Sources/Sass/component/_card.scss b/Build/Sources/Sass/component/_card.scss index df0b8022be85..d9ddf78061cd 100644 --- a/Build/Sources/Sass/component/_card.scss +++ b/Build/Sources/Sass/component/_card.scss @@ -320,11 +320,11 @@ a.card { padding-bottom: var(--typo3-card-padding); } - *:first-child { + > *:first-child:not(.row) { margin-top: 0; } - *:last-child { + > *:last-child { margin-bottom: 0; } } diff --git a/Build/Sources/Sass/component/_checkbox.scss b/Build/Sources/Sass/component/_checkbox.scss index 36fc0f2369ed..1ec6b439f6d9 100644 --- a/Build/Sources/Sass/component/_checkbox.scss +++ b/Build/Sources/Sass/component/_checkbox.scss @@ -185,14 +185,12 @@ // // Styleguide component.checkbox.3 // -$form-toggle-color: rgba(0, 0, 0, .25) !default; $form-toggle-bg-image: url("data:image/svg+xml, <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><g class='icon-color'><path d='M13 2c.6 0 1 .4 1 1v10c0 .6-.4 1-1 1H3c-.6 0-1-.4-1-1V3c0-.6.4-1 1-1h10m0-1H3c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h10c1.1 0 2-.9 2-2V3c0-1.1-.9-2-2-2z'/></g></svg>") !default; $form-toggle-checked-color: $component-active-color !default; $form-toggle-checked-bg-image: url("data:image/svg+xml, <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><g class='icon-color'><path d='M12.1 5.3l-.4-.3c-.1-.1-.3-.1-.4 0L6.6 9.8l-2-2c-.1-.1-.3-.1-.4 0l-.3.4c-.1.1-.1.3 0 .4L6 10.7l.4.3c.1.1.3.1.4 0l.4-.4 4.9-4.9c.1-.1.1-.3 0-.4z'/><path d='M13 2c.6 0 1 .4 1 1v10c0 .6-.4 1-1 1H3c-.6 0-1-.4-1-1V3c0-.6.4-1 1-1h10m0-1H3c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h10c1.1 0 2-.9 2-2V3c0-1.1-.9-2-2-2z'/></g></svg>") !default; .form-check.form-check-type-toggle { display: inline-block; - color: $form-toggle-color; padding-left: 0; margin: 0; @@ -216,3 +214,13 @@ $form-toggle-checked-bg-image: url("data:image/svg+xml, <svg xmlns='http://www.w } } } + +// +// Utility +// +// Used in .form-groups to align checkboxes with inputs +// +.form-check.form-check-size-input { + margin-top: 7px; + margin-bottom: 7px; +} diff --git a/Build/Sources/Sass/component/_code.scss b/Build/Sources/Sass/component/_code.scss index 6c84365a081b..ea9bc2849242 100644 --- a/Build/Sources/Sass/component/_code.scss +++ b/Build/Sources/Sass/component/_code.scss @@ -1,6 +1,34 @@ // // Code // +pre, +code { + hyphens: none; +} + +pre[class*="language-"], +code[class*="language-"] { + color: inherit; + background: none; + font-size: 1em; + text-align: start; + white-space: pre; + word-spacing: normal; + word-break: normal; + word-wrap: normal; + line-height: 1.5; + tab-size: 4; + hyphens: none; +} + +pre[class*="language-"] { + border-radius: 4px; + padding: 1em; + overflow: auto; + margin-bottom: var(--typo3-spacing); +} + +:not(pre) > code[class*="language-"], pre[class*="language-"] { - margin-bottom: var(--typo3-component-spacing); + background-color: rgba(0, 0, 0, .05); } diff --git a/Build/Sources/Sass/component/_form.scss b/Build/Sources/Sass/component/_form.scss index 996c71e93161..5d13f993f071 100644 --- a/Build/Sources/Sass/component/_form.scss +++ b/Build/Sources/Sass/component/_form.scss @@ -2,7 +2,35 @@ // Form // .form { - margin-bottom: var(--typo3-component-spacing); + margin-bottom: var(--typo3-spacing); +} + +// +// Row +// +@mixin make-form-row() { + display: flex; + flex-wrap: wrap; + gap: var(--typo3-spacing); + margin-bottom: var(--typo3-spacing); + + > .form-group { + margin-bottom: 0; + + > [class*="form-row"] { + margin-bottom: 0; + } + } +} + +@each $breakpoint in map-keys($grid-breakpoints) { + $infix: breakpoint-infix($breakpoint, $grid-breakpoints); + + @include media-breakpoint-up($breakpoint, $grid-breakpoints) { + .form-row#{$infix} { + @include make-form-row(); + } + } } // @@ -20,6 +48,10 @@ margin-bottom: $form-label-margin-bottom; } +.form-label + .form-description { + margin-top: calc($form-label-margin-bottom / 2 * -1); +} + // // Form group // diff --git a/Build/Sources/Sass/component/_module.scss b/Build/Sources/Sass/component/_module.scss index 241aeabff954..c7f4c6e3ba10 100644 --- a/Build/Sources/Sass/component/_module.scss +++ b/Build/Sources/Sass/component/_module.scss @@ -116,10 +116,6 @@ .module-body { padding: var(--module-body-padding); - > .callout:first-child { - margin-top: 0; - } - > .container { padding-left: 0; padding-right: 0; diff --git a/Build/Sources/Sass/component/_note.scss b/Build/Sources/Sass/component/_note.scss index d55a279159ff..7e22350fd530 100644 --- a/Build/Sources/Sass/component/_note.scss +++ b/Build/Sources/Sass/component/_note.scss @@ -68,8 +68,8 @@ $note-padding: 1rem; // .note-list { display: grid; - gap: calc(var(--typo3-component-spacing) / 2); - margin-bottom: var(--typo3-component-spacing); + gap: var(--typo3-spacing); + margin-bottom: var(--typo3-spacing); .note { margin-bottom: 0; @@ -83,7 +83,7 @@ $note-padding: 1rem; color: var(--note-color); background-color: var(--note-bg); border-radius: var(--typo3-component-border-radius); - margin-bottom: var(--typo3-component-spacing); + margin-bottom: var(--typo3-spacing); box-shadow: var(--typo3-component-box-shadow); @include note-use-variant('default'); diff --git a/Build/Sources/Sass/component/_pagination.scss b/Build/Sources/Sass/component/_pagination.scss new file mode 100644 index 000000000000..b5d1b82394c6 --- /dev/null +++ b/Build/Sources/Sass/component/_pagination.scss @@ -0,0 +1,7 @@ +// +// Pagination +// +.pagination { + flex-wrap: wrap; + row-gap: 4px; +} diff --git a/Build/Sources/Sass/component/_panel.scss b/Build/Sources/Sass/component/_panel.scss index fb761c9e2136..fb5acfc76014 100644 --- a/Build/Sources/Sass/component/_panel.scss +++ b/Build/Sources/Sass/component/_panel.scss @@ -87,7 +87,7 @@ $panel-heading-bg-scale: -85%; display: flex; flex-flow: column; overflow: hidden; - margin-bottom: var(--panel-spacing); + margin-bottom: var(--typo3-spacing); border-radius: var(--panel-border-radius); box-shadow: var(--panel-box-shadow); @@ -124,7 +124,7 @@ $panel-heading-bg-scale: -85%; border: var(--panel-border-width) solid var(--panel-border-color); border-radius: var(--panel-border-radius); box-shadow: var(--panel-box-shadow); - margin-bottom: var(--panel-spacing); + margin-bottom: var(--typo3-spacing); transition: all .2s ease-in-out; transition-property: box-shadow, border, transform; diff --git a/Build/Sources/Sass/component/_recordlist.scss b/Build/Sources/Sass/component/_recordlist.scss index 799a630f64c4..c758abc1e677 100644 --- a/Build/Sources/Sass/component/_recordlist.scss +++ b/Build/Sources/Sass/component/_recordlist.scss @@ -7,7 +7,7 @@ box-shadow: var(--panel-box-shadow); border-radius: var(--panel-border-radius); border: var(--panel-border-width) solid var(--panel-default-border-color); - margin-bottom: var(--panel-spacing); + margin-bottom: var(--typo3-spacing); table tr { td.deletePlaceholder { @@ -27,6 +27,10 @@ .pagination { display: inline-flex; } + + + .recordlist { + margin-top: calc(var(--typo3-spacing) * 1.5); + } } .recordlist-heading { diff --git a/Build/Sources/Sass/component/_recordsearchbox.scss b/Build/Sources/Sass/component/_recordsearchbox.scss index 80613438accc..5daa24f3bbeb 100644 --- a/Build/Sources/Sass/component/_recordsearchbox.scss +++ b/Build/Sources/Sass/component/_recordsearchbox.scss @@ -2,7 +2,7 @@ // Record Search Box // .recordsearchbox-container { - margin-bottom: var(--typo3-component-spacing); + margin-bottom: var(--typo3-spacing); [data-recordsearchbox-levels] { max-width: 140px; diff --git a/Build/Sources/Sass/component/_resources.scss b/Build/Sources/Sass/component/_resources.scss index c41df1eb0ab3..e4aebc2abc65 100644 --- a/Build/Sources/Sass/component/_resources.scss +++ b/Build/Sources/Sass/component/_resources.scss @@ -45,7 +45,7 @@ /* clean-css ignore:start */ .resource-tiles-container { container-type: inline-size; - margin-bottom: var(--typo3-component-spacing); + margin-bottom: var(--typo3-spacing); } @container (min-width: 480px) { @@ -200,6 +200,7 @@ padding: var(--resource-tile-spacing); text-align: center; font-size: var(--resource-tile-nameplate-size); + width: 100%; } .resource-tile-nameplate-label { diff --git a/Build/Sources/Sass/component/_root.scss b/Build/Sources/Sass/component/_root.scss index 69cb52d3399c..d6d112b71a16 100644 --- a/Build/Sources/Sass/component/_root.scss +++ b/Build/Sources/Sass/component/_root.scss @@ -78,7 +78,7 @@ --typo3-component-disabled-color: var(--typo3-light-disabled-color); --typo3-component-disabled-bg: var(--typo3-light-disabled-bg); --typo3-component-disabled-border-color: var(--typo3-light-disabled-border-color); - --typo3-component-spacing: 1.5rem; + --typo3-component-spacing: 2rem; // List --typo3-list-item-padding-y: .5rem; diff --git a/Build/Sources/Sass/component/_spacer.scss b/Build/Sources/Sass/component/_spacer.scss new file mode 100644 index 000000000000..4b63e2d1f5da --- /dev/null +++ b/Build/Sources/Sass/component/_spacer.scss @@ -0,0 +1,13 @@ +// +// Spacer +// +// Usage +// ----- +// +// <hr class="spacer"> +// +hr.spacer { + border-top: none; + margin-top: var(--typo3-spacing); + margin-bottom: var(--typo3-spacing); +} diff --git a/Build/Sources/Sass/component/_statusreport.scss b/Build/Sources/Sass/component/_statusreport.scss index f557e16823f7..d0ba5b692a21 100644 --- a/Build/Sources/Sass/component/_statusreport.scss +++ b/Build/Sources/Sass/component/_statusreport.scss @@ -104,7 +104,7 @@ .statusreport-wrapper { border-radius: var(--statusreport-border-radius); box-shadow: var(--statusreport-box-shadow); - margin-bottom: var(--typo3-component-spacing); + margin-bottom: var(--typo3-spacing); .statusreport { &:first-child { diff --git a/Build/Sources/Sass/component/_table.scss b/Build/Sources/Sass/component/_table.scss index 52775a95e2ca..919f74a1c351 100644 --- a/Build/Sources/Sass/component/_table.scss +++ b/Build/Sources/Sass/component/_table.scss @@ -193,7 +193,7 @@ td.selected { width: 100%; border-radius: var(--typo3-component-border-radius); box-shadow: var(--typo3-component-box-shadow); - margin-bottom: var(--typo3-component-spacing); + margin-bottom: var(--typo3-spacing); overflow-x: auto; overflow-y: hidden; -webkit-overflow-scrolling: touch; diff --git a/Build/Sources/Sass/component/_type.scss b/Build/Sources/Sass/component/_type.scss new file mode 100644 index 000000000000..f5d3efe070e5 --- /dev/null +++ b/Build/Sources/Sass/component/_type.scss @@ -0,0 +1,26 @@ +// +// Type Adjustments +// +h1 { + font-family: var(--typo3-header-font-family); + font-variant: normal; + font-weight: 400; +} + +h1, +h2, +h3 { + &.headline-spaced, + &:not(:first-child):not([class]) { + margin-top: calc(var(--typo3-spacing) * 2); + } +} + +.h1, +.h2, +.h3, +.h4, +.h5, +.h6 { + font-family: inherit; +} diff --git a/Build/Sources/Sass/module/_install.scss b/Build/Sources/Sass/module/_install.scss index 389dc607a639..81ffeb6c5b67 100644 --- a/Build/Sources/Sass/module/_install.scss +++ b/Build/Sources/Sass/module/_install.scss @@ -92,7 +92,9 @@ // Styles for specific modals: image processing .t3-install-displaytwinimageimages { border: 1px solid #ccc; + border-radius: 4px; padding: 10px; + margin-bottom: var(--typo3-spacing); } .t3-install-displaytwinimagetextarea { diff --git a/Build/Sources/Sass/module/_page.scss b/Build/Sources/Sass/module/_page.scss index ce51b6985493..f4ce1ffe31c2 100644 --- a/Build/Sources/Sass/module/_page.scss +++ b/Build/Sources/Sass/module/_page.scss @@ -46,7 +46,7 @@ html { .t3-grid-container { overflow: hidden; - margin-bottom: var(--typo3-component-spacing); + margin-bottom: var(--typo3-spacing); } .t3-grid-container-inner { diff --git a/Build/Sources/Sass/module/_scheduler.scss b/Build/Sources/Sass/module/_scheduler.scss index b2f1fa56045c..1c7ec3400e63 100644 --- a/Build/Sources/Sass/module/_scheduler.scss +++ b/Build/Sources/Sass/module/_scheduler.scss @@ -11,10 +11,6 @@ } } -.scheduler-group-panel { - overflow: unset; -} - .task-form .form-wizards-wrap { margin-bottom: .5rem !important; } diff --git a/Build/Sources/Sass/typo3/_main_content.scss b/Build/Sources/Sass/typo3/_main_content.scss index 1812a873227f..fb7384c80c07 100644 --- a/Build/Sources/Sass/typo3/_main_content.scss +++ b/Build/Sources/Sass/typo3/_main_content.scss @@ -1,12 +1,6 @@ // // TYPO3 styles for basic elements // -h1 { - font-family: var(--typo3-header-font-family); - font-variant: normal; - font-weight: 400; -} - video { background-color: #000; } @@ -22,13 +16,6 @@ video { white-space: normal !important; } -// -// TYPO3 styles for basic elements -// -em { - font-style: italic; -} - // // Various classes // diff --git a/Build/Sources/Sass/typo3/_main_form.scss b/Build/Sources/Sass/typo3/_main_form.scss index c99b4d5cbc7a..cc63b511c8e7 100644 --- a/Build/Sources/Sass/typo3/_main_form.scss +++ b/Build/Sources/Sass/typo3/_main_form.scss @@ -119,23 +119,6 @@ fieldset[disabled] .form-control { color: $input-color-disabled; } -// -// Form control icon -// -.form-control-icon { - position: absolute; - top: 50%; - left: 15px; - transform: translate(0, -50%); - z-index: 1; - pointer-events: none; - - + .form-control, - + .form-control-clearable .form-control { - padding-left: 3.25em; - } -} - // // Form group validation states // @@ -192,9 +175,17 @@ select { } // -// Styles for the "clearable" jquery plugin. +// Styles for the "clearable" plugin. +// +// <div class="form-control-clearable-wrapper"> +// <input type="text" class="form-control form-control-clearable" /> +// </div> // .form-control-clearable { + padding-right: 2.3em; +} + +.form-control-clearable-wrapper { position: relative; border: 0; padding: 0; @@ -445,13 +436,13 @@ textarea { // with a clearable div. If the field is unlocked for explanation view, the // wrap should grow to 100%, else it should shrink to 0%. // -.input-group > .form-control-clearable { +.input-group > .form-control-clearable-wrapper { flex: 1 1 auto; width: 1%; min-width: 0; } -.form-control:not(.hidden) + .form-control-clearable { +.form-control:not(.hidden) + .form-control-clearable-wrapper { flex-grow: 0; width: auto; } diff --git a/Build/Sources/Sass/variables/_main.scss b/Build/Sources/Sass/variables/_main.scss index 0423c1bc82e6..3a3fdc285a61 100644 --- a/Build/Sources/Sass/variables/_main.scss +++ b/Build/Sources/Sass/variables/_main.scss @@ -76,16 +76,16 @@ $font-family-sans-serif: Verdana, Arial, Helvetica, sans-serif; $font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; $font-size-root: 16px; $font-size-base: 12px; -$font-size-large: ceil(($font-size-base * 1.25)); // ~15px -$font-size-small: 11px; // ~11px -$h1-font-size: $font-size-base * 2.25; -$h2-font-size: $font-size-base * 1.6; -$h3-font-size: $font-size-base * 1.4; -$h4-font-size: $font-size-base * 1.25; -$headings-line-height: 1.1; - -// Paragraphs -$paragraph-margin-bottom: .5rem; +$font-size-large: 16px; +$font-size-small: 11px; +$h1-font-size: 28px; +$h2-font-size: 20px; +$h3-font-size: 16px; +$h4-font-size: 14px; + +// Spacings +$headings-margin-bottom: calc(var(--typo3-spacing) / 2); +$paragraph-margin-bottom: var(--typo3-spacing); // Components $padding-base-vertical: 6px; diff --git a/Build/Sources/TypeScript/backend/form-engine.ts b/Build/Sources/TypeScript/backend/form-engine.ts index ac5382619f8c..1b6a1009d613 100644 --- a/Build/Sources/TypeScript/backend/form-engine.ts +++ b/Build/Sources/TypeScript/backend/form-engine.ts @@ -720,10 +720,10 @@ export default (function() { */ FormEngine.reinitialize = function(): void { // Apply "close" button to all input / datetime fields - const clearables = Array.from(document.querySelectorAll('.t3js-clearable')); + const clearables = document.querySelectorAll('.t3js-clearable') as NodeListOf<HTMLInputElement>; if (clearables.length > 0) { import('@typo3/backend/input/clearable').then(function() { - clearables.forEach(clearableField => (clearableField as any).clearable()); + clearables.forEach(clearableField => clearableField.clearable()); }); } diff --git a/Build/Sources/TypeScript/backend/form-engine/field-control/password-generator.ts b/Build/Sources/TypeScript/backend/form-engine/field-control/password-generator.ts index 6f87495e1703..5cf040b83238 100644 --- a/Build/Sources/TypeScript/backend/form-engine/field-control/password-generator.ts +++ b/Build/Sources/TypeScript/backend/form-engine/field-control/password-generator.ts @@ -57,7 +57,7 @@ class PasswordGenerator { // Also remove clearable possibility if (this.humanReadableField.isClearable || this.humanReadableField.classList.contains('t3js-clearable')) { this.humanReadableField.classList.remove('t3js-clearable'); - const clearableContainer = <HTMLDivElement>this.humanReadableField.closest('div.form-control-clearable'); + const clearableContainer = <HTMLDivElement>this.humanReadableField.closest('div.form-control-clearable-wrapper'); if (clearableContainer) { clearableContainer.classList.remove('form-control-clearable'); const closeButton = <HTMLButtonElement>clearableContainer.querySelector('button.close'); diff --git a/Build/Sources/TypeScript/backend/input/clearable.ts b/Build/Sources/TypeScript/backend/input/clearable.ts index 42bd3b174bf7..f33c4ea858a3 100644 --- a/Build/Sources/TypeScript/backend/input/clearable.ts +++ b/Build/Sources/TypeScript/backend/input/clearable.ts @@ -68,8 +68,10 @@ class Clearable { throw new Error('Passed options must be an object, ' + typeof options + ' given'); } + this.classList.add('form-control-clearable'); + const wrap = document.createElement('div'); - wrap.classList.add('form-control-clearable'); + wrap.classList.add('form-control-clearable-wrapper'); this.parentNode.insertBefore(wrap, this); wrap.appendChild(this); diff --git a/Build/Sources/TypeScript/backend/login.ts b/Build/Sources/TypeScript/backend/login.ts index 13374cdd8649..ff5d8484b371 100644 --- a/Build/Sources/TypeScript/backend/login.ts +++ b/Build/Sources/TypeScript/backend/login.ts @@ -176,7 +176,7 @@ class BackendLogin { private initializeEvents(): void { new RegularEvent('submit', this.handleSubmit.bind(this)).bindTo(document.querySelector(this.options.loginForm)); - (<NodeListOf<HTMLInputElement>>document.querySelectorAll('.t3js-clearable')).forEach( + (document.querySelectorAll('.t3js-clearable') as NodeListOf<HTMLInputElement>).forEach( (clearableField: HTMLInputElement) => clearableField.clearable(), ); } diff --git a/Build/Sources/TypeScript/belog/backend-log.ts b/Build/Sources/TypeScript/belog/backend-log.ts index 60102c20f395..8b785dfca51a 100644 --- a/Build/Sources/TypeScript/belog/backend-log.ts +++ b/Build/Sources/TypeScript/belog/backend-log.ts @@ -29,7 +29,7 @@ class BackendLog { constructor() { DocumentService.ready().then((): void => { - this.clearableElements = document.querySelectorAll('.t3js-clearable'); + this.clearableElements = document.querySelectorAll('.t3js-clearable') as NodeListOf<HTMLInputElement>; this.dateTimePickerElements = document.querySelectorAll('.t3js-datetimepicker'); this.elementBrowserElements = document.querySelectorAll('.t3js-element-browser'); this.initializeClearableElements(); @@ -41,7 +41,7 @@ class BackendLog { private initializeClearableElements(): void { this.clearableElements.forEach( - (clearableField: HTMLInputElement) => clearableField.clearable() + (clearableField) => clearableField.clearable() ); } diff --git a/Build/Sources/TypeScript/install/renderable/clearable.ts b/Build/Sources/TypeScript/install/renderable/clearable.ts index d5b69a839481..5c523ae3d410 100644 --- a/Build/Sources/TypeScript/install/renderable/clearable.ts +++ b/Build/Sources/TypeScript/install/renderable/clearable.ts @@ -68,8 +68,10 @@ class Clearable { throw new Error('Passed options must be an object, ' + typeof options + ' given'); } + this.classList.add('form-control-clearable'); + const wrap = document.createElement('div'); - wrap.classList.add('form-control-clearable', 'form-control'); + wrap.classList.add('form-control-clearable-wrapper'); this.parentNode.insertBefore(wrap, this); wrap.appendChild(this); diff --git a/Build/Sources/TypeScript/lowlevel/query-generator.ts b/Build/Sources/TypeScript/lowlevel/query-generator.ts index 77a971d6de5b..5d77b0c1069a 100644 --- a/Build/Sources/TypeScript/lowlevel/query-generator.ts +++ b/Build/Sources/TypeScript/lowlevel/query-generator.ts @@ -11,55 +11,52 @@ * The TYPO3 project - inspiring people to share! */ -import $ from 'jquery'; import '@typo3/backend/input/clearable'; import DateTimePicker from '@typo3/backend/date-time-picker'; +import RegularEvent from '@typo3/core/event/regular-event'; /** * Module: @typo3/lowlevel/query-generator * This module handle the QueryGenerator forms. */ class QueryGenerator { - private form: JQuery = null; - private limitField: JQuery = null; + private form: HTMLFormElement = null; + private limitField: HTMLInputElement = null; constructor() { - this.initialize(); - } + this.form = document.querySelector('form[name="queryform"]'); + this.limitField = document.querySelector('input#queryLimit'); - /** - * Initialize the QueryGenerator object - */ - private initialize(): void { - this.form = $('form[name="queryform"]'); - this.limitField = $('#queryLimit'); - this.form.on('click', '.t3js-submit-click', (e: JQueryEventObject): void => { - e.preventDefault(); + new RegularEvent('click', (event: Event) => { + event.preventDefault(); this.doSubmit(); - }); - this.form.on('change', '.t3js-submit-change', (e: JQueryEventObject): void => { - e.preventDefault(); + }).delegateTo(this.form, '.t3js-submit-click'); + + new RegularEvent('change', (event: Event) => { + event.preventDefault(); this.doSubmit(); - }); - this.form.on('click', '.t3js-limit-submit input[type="button"]', (e: JQueryEventObject): void => { - e.preventDefault(); - this.setLimit($(e.currentTarget).data('value')); + }).delegateTo(this.form, '.t3js-submit-change'); + + new RegularEvent('click', (event: Event, element: HTMLButtonElement) => { + event.preventDefault(); + this.setLimit(element.value); this.doSubmit(); - }); - this.form.on('click', '.t3js-addfield', (e: JQueryEventObject): void => { - e.preventDefault(); - const $field = $(e.currentTarget); - this.addValueToField($field.data('field'), $field.val()); - }); - this.form.on('change', '[data-assign-store-control-title]', (evt: JQueryEventObject): void => { - const $currentTarget = $(evt.currentTarget); - const $titleField = this.form.find('[name="storeControl[title]"]'); - if ($currentTarget.val() !== '0') { - $titleField.val($currentTarget.find('option:selected').text()); + }).delegateTo(this.form, '.t3js-limit-submit input[type="button"]'); + + new RegularEvent('click', (event: Event, element: HTMLButtonElement) => { + event.preventDefault(); + this.addValueToField(element.dataset.field, element.value); + }).delegateTo(this.form, '.t3js-addfield'); + + new RegularEvent('change', (event: Event, element: HTMLSelectElement) => { + const titleField = <HTMLInputElement>this.form.querySelector('input[name="storeControl[title]"]'); + if (element.value !== '0') { + titleField.value = element.querySelector('option:selected').textContent; } else { - $titleField.val(''); + titleField.value = ''; } - }); + }).delegateTo(this.form, 'select.t3js-addfield'); + (<NodeListOf<HTMLInputElement>>document.querySelectorAll('form[name="queryform"] .t3js-clearable')).forEach( (clearableField: HTMLInputElement) => clearableField.clearable({ onClear: (): void => { @@ -76,7 +73,7 @@ class QueryGenerator { * Submit the form */ private doSubmit(): void { - this.form.trigger('submit'); + this.form.submit(); } /** @@ -85,7 +82,7 @@ class QueryGenerator { * @param {String} value */ private setLimit(value: string): void { - this.limitField.val(value); + this.limitField.value = value; } /** @@ -95,9 +92,15 @@ class QueryGenerator { * @param {String} value the value to add */ private addValueToField(field: string, value: string): void { - const $target = this.form.find('[name="' + field + '"]'); - const currentValue = $target.val(); - $target.val(currentValue + ',' + value); + const target = <HTMLInputElement>this.form.querySelector('[name="' + field + '"]'); + value = target.value + ',' + value; + target.value = value + .split(',') + // Remove whitespace from fields + .map(fieldName => fieldName.trim()) + // Ensure fields only exist once + .filter((value, index, array) => array.indexOf(value) === index) + .join(','); } } diff --git a/typo3/sysext/backend/Classes/Controller/RecordListController.php b/typo3/sysext/backend/Classes/Controller/RecordListController.php index c76b467c89d0..d87d5e642021 100644 --- a/typo3/sysext/backend/Classes/Controller/RecordListController.php +++ b/typo3/sysext/backend/Classes/Controller/RecordListController.php @@ -195,7 +195,7 @@ class RecordListController } $clipboardHtml = ''; if ($this->allowClipboard && $this->moduleData->get('clipBoard') && ($tableListHtml || $clipboard->hasElements())) { - $clipboardHtml = '<typo3-backend-clipboard-panel return-url="' . htmlspecialchars($dbList->listURL()) . '"></typo3-backend-clipboard-panel>'; + $clipboardHtml = '<hr class="spacer"><typo3-backend-clipboard-panel return-url="' . htmlspecialchars($dbList->listURL()) . '"></typo3-backend-clipboard-panel>'; } $view->setTitle($languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_mod_web_list.xlf:mlang_tabs_tab'), $title); @@ -519,10 +519,14 @@ class RecordListController $output .= '<option value="' . htmlspecialchars($targetUrl) . '">' . htmlspecialchars($languageTitle) . '</option>'; } - return '<div class="row row-cols-auto align-items-end g-3 mb-4"><div class="col"><div class="form-group">' - . '<select class="form-select" name="createNewLanguage" data-global-event="change" data-action-navigate="$value">' - . $output - . '</select></div></div></div>'; + return '' + . '<div class="form-row">' + . '<div class="form-group">' + . '<select class="form-select" name="createNewLanguage" data-global-event="change" data-action-navigate="$value">' + . $output + . '</select>' + . '</div>' + . '</div>'; } return ''; } diff --git a/typo3/sysext/backend/Classes/Form/Element/DatetimeElement.php b/typo3/sysext/backend/Classes/Form/Element/DatetimeElement.php index df58837a3c04..3b027d080c74 100644 --- a/typo3/sysext/backend/Classes/Form/Element/DatetimeElement.php +++ b/typo3/sysext/backend/Classes/Form/Element/DatetimeElement.php @@ -139,6 +139,7 @@ class DatetimeElement extends AbstractFormElement 'class' => implode(' ', [ 't3js-datetimepicker', 'form-control', + 'form-control-clearable', 't3js-clearable', 'hasDefaultValue', ]), diff --git a/typo3/sysext/backend/Classes/Form/Element/EmailElement.php b/typo3/sysext/backend/Classes/Form/Element/EmailElement.php index fceaff013992..45784856ed16 100644 --- a/typo3/sysext/backend/Classes/Form/Element/EmailElement.php +++ b/typo3/sysext/backend/Classes/Form/Element/EmailElement.php @@ -118,6 +118,7 @@ class EmailElement extends AbstractFormElement 'maxlength' => '254', 'class' => implode(' ', [ 'form-control', + 'form-control-clearable', 't3js-clearable', 'hasDefaultValue', ]), diff --git a/typo3/sysext/backend/Classes/Form/Element/InputTextElement.php b/typo3/sysext/backend/Classes/Form/Element/InputTextElement.php index c395bc8c65ad..98e47ad5b41b 100644 --- a/typo3/sysext/backend/Classes/Form/Element/InputTextElement.php +++ b/typo3/sysext/backend/Classes/Form/Element/InputTextElement.php @@ -134,6 +134,7 @@ class InputTextElement extends AbstractFormElement 'id' => $fieldId, 'class' => implode(' ', [ 'form-control', + 'form-control-clearable', 't3js-clearable', 'hasDefaultValue', ]), diff --git a/typo3/sysext/backend/Classes/Form/Element/LinkElement.php b/typo3/sysext/backend/Classes/Form/Element/LinkElement.php index ed724b621975..08b4db308cb2 100644 --- a/typo3/sysext/backend/Classes/Form/Element/LinkElement.php +++ b/typo3/sysext/backend/Classes/Form/Element/LinkElement.php @@ -136,6 +136,7 @@ class LinkElement extends AbstractFormElement 'id' => $fieldId, 'class' => implode(' ', [ 'form-control', + 'form-control-clearable', 't3js-clearable', 't3js-form-field-link-input', 'hidden', diff --git a/typo3/sysext/backend/Classes/Form/Element/NumberElement.php b/typo3/sysext/backend/Classes/Form/Element/NumberElement.php index fe67c21a5ccb..254e558e143b 100644 --- a/typo3/sysext/backend/Classes/Form/Element/NumberElement.php +++ b/typo3/sysext/backend/Classes/Form/Element/NumberElement.php @@ -128,6 +128,7 @@ class NumberElement extends AbstractFormElement 'id' => $fieldId, 'class' => implode(' ', [ 'form-control', + 'form-control-clearable', 't3js-clearable', 'hasDefaultValue', ]), diff --git a/typo3/sysext/backend/Classes/Form/Element/PasswordElement.php b/typo3/sysext/backend/Classes/Form/Element/PasswordElement.php index 512f8ea54f21..df030d4b3ba2 100644 --- a/typo3/sysext/backend/Classes/Form/Element/PasswordElement.php +++ b/typo3/sysext/backend/Classes/Form/Element/PasswordElement.php @@ -114,6 +114,7 @@ class PasswordElement extends AbstractFormElement 'spellcheck' => 'false', 'class' => implode(' ', [ 'form-control', + 'form-control-clearable', 't3js-clearable', 'hasDefaultValue', ]), diff --git a/typo3/sysext/backend/Resources/Private/Layouts/Module.html b/typo3/sysext/backend/Resources/Private/Layouts/Module.html index 9bec2bfa254e..f39e93aac4e5 100644 --- a/typo3/sysext/backend/Resources/Private/Layouts/Module.html +++ b/typo3/sysext/backend/Resources/Private/Layouts/Module.html @@ -3,6 +3,8 @@ data-namespace-typo3-fluid="true" > +<f:render section="Before" arguments="{_all}" optional="true" /> + <div class="module {moduleClass}" data-module-id="{moduleId}" data-module-name="{moduleName}"> <f:if condition="{formTag}"> <f:then> @@ -30,4 +32,6 @@ </f:if> </div> +<f:render section="After" arguments="{_all}" optional="true" /> + </html> diff --git a/typo3/sysext/backend/Resources/Private/Partials/About/Logo.html b/typo3/sysext/backend/Resources/Private/Partials/About/Logo.html index 9b94daa31505..f454b031309e 100644 --- a/typo3/sysext/backend/Resources/Private/Partials/About/Logo.html +++ b/typo3/sysext/backend/Resources/Private/Partials/About/Logo.html @@ -1,7 +1,8 @@ -<img src="{f:uri.resource(path: 'EXT:core/Resources/Public/Images/typo3_orange.svg')}" width="150" - alt="{f:translate(key:'LLL:EXT:backend/Resources/Private/Language/Modules/about.xlf:typo3_logo')}" /> -<br> -<br> +<img + src="{f:uri.resource(path: 'EXT:core/Resources/Public/Images/typo3_orange.svg')}" + width="150" + alt="{f:translate(key:'LLL:EXT:backend/Resources/Private/Language/Modules/about.xlf:typo3_logo')}" +/> <h1> TYPO3 CMS {typo3Version.version}<br> <f:translate key="LLL:EXT:backend/Resources/Private/Language/Modules/about.xlf:introtext" /> diff --git a/typo3/sysext/backend/Resources/Private/Partials/PageLayout/LanguageColumns.html b/typo3/sysext/backend/Resources/Private/Partials/PageLayout/LanguageColumns.html index 633dd70624cc..e1ebf51f6f52 100644 --- a/typo3/sysext/backend/Resources/Private/Partials/PageLayout/LanguageColumns.html +++ b/typo3/sysext/backend/Resources/Private/Partials/PageLayout/LanguageColumns.html @@ -1,6 +1,6 @@ <f:if condition="{context.newLanguageOptions}"> - <div class="row row-cols-auto align-items-end g-3 mb-4"> - <div class="col"> + <div class="form-row"> + <div class="form-group"> <select class="form-select" name="createNewLanguage" data-global-event="change" data-action-navigate="$value"> <f:for each="{context.newLanguageOptions}" as="languageName" key="url"> <option value="{url}">{languageName}</option> diff --git a/typo3/sysext/backend/Resources/Private/Templates/Login/ForgetPasswordForm.html b/typo3/sysext/backend/Resources/Private/Templates/Login/ForgetPasswordForm.html index 5571b9b1e874..59a40414e582 100644 --- a/typo3/sysext/backend/Resources/Private/Templates/Login/ForgetPasswordForm.html +++ b/typo3/sysext/backend/Resources/Private/Templates/Login/ForgetPasswordForm.html @@ -28,7 +28,7 @@ <div class="form-control-wrap"> <div class="form-control-holder"> <label for="typo3-forget-password-email"><f:translate key="LLL:EXT:backend/Resources/Private/Language/locallang_reset_password.xlf:input.email" /></label> - <input type="email" name="email" value="{email}" placeholder="you@example.com" id="typo3-forget-password-email" class="form-control input-login t3js-clearable" autofocus="autofocus" autocomplete="email" required="required" /> + <input type="email" name="email" value="{email}" placeholder="you@example.com" id="typo3-forget-password-email" class="form-control form-control-clearable input-login t3js-clearable" autofocus="autofocus" autocomplete="email" required="required" /> </div> </div> </div> diff --git a/typo3/sysext/backend/Resources/Private/Templates/Login/ResetPasswordForm.html b/typo3/sysext/backend/Resources/Private/Templates/Login/ResetPasswordForm.html index 3406600515f9..ae4bede0bf46 100644 --- a/typo3/sysext/backend/Resources/Private/Templates/Login/ResetPasswordForm.html +++ b/typo3/sysext/backend/Resources/Private/Templates/Login/ResetPasswordForm.html @@ -44,7 +44,7 @@ name="password" placeholder="{f:translate(key: 'LLL:EXT:backend/Resources/Private/Language/locallang_reset_password.xlf:input.password')}" value="" - class="form-control input-login t3js-clearable t3js-login-password-field" + class="form-control form-control-clearable input-login t3js-clearable t3js-login-password-field" autocomplete="new-password" autofocus="autofocus" required="required" @@ -73,7 +73,7 @@ placeholder="{f:translate(key: 'LLL:EXT:backend/Resources/Private/Language/locallang_reset_password.xlf:input.passwordrepeat')}" value="" autocomplete="off" - class="form-control input-login t3js-clearable t3js-login-password-field" + class="form-control form-control-clearable input-login t3js-clearable t3js-login-password-field" required="required" spellcheck="false" /> diff --git a/typo3/sysext/backend/Resources/Private/Templates/Login/UserPassLoginForm.html b/typo3/sysext/backend/Resources/Private/Templates/Login/UserPassLoginForm.html index 686bd447fbc2..00738c8a9683 100644 --- a/typo3/sysext/backend/Resources/Private/Templates/Login/UserPassLoginForm.html +++ b/typo3/sysext/backend/Resources/Private/Templates/Login/UserPassLoginForm.html @@ -23,7 +23,7 @@ value="{presetUsername}" aria-label="{f:translate(key: 'LLL:EXT:backend/Resources/Private/Language/locallang.xlf:login.username')}" placeholder="{f:translate(key: 'LLL:EXT:backend/Resources/Private/Language/locallang.xlf:login.username')}" - class="form-control input-login t3js-clearable t3js-login-username-field" + class="form-control form-control-clearable input-login t3js-clearable t3js-login-username-field" autofocus="autofocus" autocomplete="username" required="required" diff --git a/typo3/sysext/backend/Resources/Private/Templates/Page/NewPages.html b/typo3/sysext/backend/Resources/Private/Templates/Page/NewPages.html index 77ab579f02f3..8051d120b0d7 100644 --- a/typo3/sysext/backend/Resources/Private/Templates/Page/NewPages.html +++ b/typo3/sysext/backend/Resources/Private/Templates/Page/NewPages.html @@ -198,17 +198,13 @@ <div class="formengine-field-item t3js-formengine-field-item"> <div class="form-control-wrap"> <div class="form-wizards-wrap"> - <div class="form-wizards-element"> - <div class="form-control-clearable"> - <input - class="form-control t3js-newmultiplepages-page-title" - type="text" - id="page_new_{line.index}" - name="pages[NEW{line.index}][title]" - placeholder="{f:translate(key: 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.title')}" - /> - </div> - </div> + <input + class="form-control t3js-newmultiplepages-page-title" + type="text" + id="page_new_{line.index}" + name="pages[NEW{line.index}][title]" + placeholder="{f:translate(key: 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.title')}" + /> </div> </div> </div> diff --git a/typo3/sysext/backend/Resources/Private/Templates/PageLayout/PageModule.html b/typo3/sysext/backend/Resources/Private/Templates/PageLayout/PageModule.html index 1cc365fa5873..2175923f0503 100644 --- a/typo3/sysext/backend/Resources/Private/Templates/PageLayout/PageModule.html +++ b/typo3/sysext/backend/Resources/Private/Templates/PageLayout/PageModule.html @@ -5,8 +5,7 @@ <f:layout name="Module" /> -<f:section name="Content"> - +<f:section name="Before"> <f:be.pageRenderer includeJavaScriptModules="{ 0: '@typo3/backend/clear-cache.js', @@ -18,9 +17,14 @@ 6: '@typo3/backend/element/editable-page-title.js' }" /> - <f:variable name="immediateActionArgs" value="{0: 'web', 1: pageId, 2: 1}" /> - <typo3-immediate-action action="TYPO3.Backend.Storage.ModuleStateStorage.updateWithCurrentMount" args="{immediateActionArgs -> f:format.json() -> f:format.htmlspecialchars()}"></typo3-immediate-action> + <typo3-immediate-action + action="TYPO3.Backend.Storage.ModuleStateStorage.updateWithCurrentMount" + args="{immediateActionArgs -> f:format.json() -> f:format.htmlspecialchars()}" + ></typo3-immediate-action> +</f:section> + +<f:section name="Content"> <f:for each="{infoBoxes}" as="infoBox"> <f:be.infobox state="{infoBox.state}"> diff --git a/typo3/sysext/backend/Resources/Private/Templates/PageLayout/PageModuleNoAccess.html b/typo3/sysext/backend/Resources/Private/Templates/PageLayout/PageModuleNoAccess.html index e9e3e402a358..0ca68f9b6927 100644 --- a/typo3/sysext/backend/Resources/Private/Templates/PageLayout/PageModuleNoAccess.html +++ b/typo3/sysext/backend/Resources/Private/Templates/PageLayout/PageModuleNoAccess.html @@ -5,13 +5,17 @@ <f:layout name="Module" /> -<f:section name="Content"> - +<f:section name="Before"> <f:variable name="immediateActionArgs" value="{0: 'web', 1: pageId}" /> - <typo3-immediate-action action="TYPO3.Backend.Storage.ModuleStateStorage.update" args="{immediateActionArgs -> f:format.json() -> f:format.htmlspecialchars()}"></typo3-immediate-action> + <typo3-immediate-action + action="TYPO3.Backend.Storage.ModuleStateStorage.update" + args="{immediateActionArgs -> f:format.json() -> f:format.htmlspecialchars()}" + ></typo3-immediate-action> +</f:section> - <h1>{siteName}</h1> +<f:section name="Content"> + <h1>{siteName}</h1> <f:be.infobox message="{f:translate(key: 'LLL:EXT:backend/Resources/Private/Language/locallang_layout.xlf:clickAPage_content')}" state="-1" /> </f:section> diff --git a/typo3/sysext/backend/Resources/Private/Templates/PageTsConfig/Active.html b/typo3/sysext/backend/Resources/Private/Templates/PageTsConfig/Active.html index 995385365370..1d6f1ecb5a45 100644 --- a/typo3/sysext/backend/Resources/Private/Templates/PageTsConfig/Active.html +++ b/typo3/sysext/backend/Resources/Private/Templates/PageTsConfig/Active.html @@ -7,7 +7,7 @@ <f:layout name="Module"/> -<f:section name="Content"> +<f:section name="Before"> <f:be.pageRenderer includeJavaScriptModules="{ 0: '@typo3/backend/context-menu.js', @@ -20,10 +20,14 @@ 'collapse-state-search.numberOfSearchMatches': 'LLL:EXT:backend/Resources/Private/Language/locallang_pagetsconfig.xlf:module.pagetsconfig_active.panel.header.numberOfSearchMatches' }" /> - <f:variable name="args" value="{0: 'web', 1: pageUid}" /> - <typo3-immediate-action action="TYPO3.Backend.Storage.ModuleStateStorage.update" args="{args -> f:format.json() -> f:format.htmlspecialchars()}"></typo3-immediate-action> + <typo3-immediate-action + action="TYPO3.Backend.Storage.ModuleStateStorage.update" + args="{args -> f:format.json() -> f:format.htmlspecialchars()}" + ></typo3-immediate-action> +</f:section> +<f:section name="Content"> <h1> <f:translate key="LLL:EXT:backend/Resources/Private/Language/locallang_pagetsconfig.xlf:module.pagetsconfig_active.headline" @@ -89,13 +93,13 @@ </f:section> <f:section name="Options"> - <div class="row row-cols-auto align-items-end g-3 mb-4 pt-2"> - <div class="col col-12 col-sm-6 col-md-5 col-lg-4 col-xl-3"> + <div class="form-row-md"> + <div class="form-group"> <form action="#"> <div class="input-group"> <input type="text" - class="form-control t3js-collapse-search-term" + class="form-control form-control-clearable t3js-collapse-search-term" name="searchValue" data-persist-collapse-search-key="collapse-search-term-pagets" value="" @@ -106,13 +110,13 @@ </div> </form> </div> - <div class="col"> - <div class="row row-cols-md-auto pb-1"> + <div class="form-group"> + <div class="form-row-sm"> <f:if condition="{siteSettingsAst}"> - <div class="col col-12 col-sm-12"> + <div class="form-group"> <form action="{f:be.uri(route: 'pagetsconfig_active', parameters: '{id: pageUid}')}" method="post"> <input type="hidden" name="displayConstantSubstitutions" value="0" /> - <div class="form-check form-switch"> + <div class="form-check form-switch form-check-size-input"> <input type="checkbox" class="form-check-input" @@ -131,10 +135,10 @@ </form> </div> </f:if> - <div class="col col-12 col-sm-12"> + <div class="form-group"> <form action="{f:be.uri(route: 'pagetsconfig_active', parameters: '{id: pageUid}')}" method="post"> <input type="hidden" name="displayComments" value="0" /> - <div class="form-check form-switch"> + <div class="form-check form-switch form-check-size-input"> <input type="checkbox" class="form-check-input" @@ -152,10 +156,10 @@ </div> </form> </div> - <div class="col col-12 col-sm-12"> + <div class="form-group"> <form action="{f:be.uri(route: 'pagetsconfig_active', parameters: '{id: pageUid}')}" method="post"> <input type="hidden" name="sortAlphabetically" value="0" /> - <div class="form-check form-switch"> + <div class="form-check form-switch form-check-size-input"> <input type="checkbox" class="form-check-input" @@ -236,46 +240,42 @@ > <div class="panel-body"> <form action="{f:be.uri(route: 'pagetsconfig_active', parameters: '{id: pageUid}')}" method="post"> - <div class="row"> - <div class="col-12"> - <f:for each="{conditions}" as="condition"> - <input type="hidden" name="pageTsConfigConditions[{condition.hash}]" value="0" /> - <div class="form-check form-switch"> - <input - type="checkbox" - class="form-check-input" - id="condition{condition.hash}" - name="pageTsConfigConditions[{condition.hash}]" - value="1" - data-global-event="change" - data-action-submit="$form" - data-value-selector="input[name='pageTsConfigConditions[{condition.hash}]']" - {f:if(condition: condition.active, then: 'checked="checked"')} - /> - <label class="form-check-label" for="condition{condition.hash}"> - <f:if condition="{displayConstantSubstitutions} && {condition.originalValue}"> - <f:then> - <span class="font-monospace">[{condition.value}]</span> - <span class="diff-item-result diff-item-result-inline font-monospace p-0"> - <f:format.raw> - <f:translate - key="LLL:EXT:backend/Resources/Private/Language/locallang_pagetsconfig.xlf:module.pagetsconfig_active.panel.info.conditionWithConstant" - arguments="{ - 0: '{backend:typoScript.fineDiff(from: condition.originalValue, to: condition.value)}' - }" - /> - </f:format.raw> - </span> - </f:then> - <f:else> - <span class="font-monospace">[{condition.value}]</span> - </f:else> - </f:if> - </label> - </div> - </f:for> + <f:for each="{conditions}" as="condition"> + <input type="hidden" name="pageTsConfigConditions[{condition.hash}]" value="0" /> + <div class="form-check form-switch"> + <input + type="checkbox" + class="form-check-input" + id="condition{condition.hash}" + name="pageTsConfigConditions[{condition.hash}]" + value="1" + data-global-event="change" + data-action-submit="$form" + data-value-selector="input[name='pageTsConfigConditions[{condition.hash}]']" + {f:if(condition: condition.active, then: 'checked="checked"')} + /> + <label class="form-check-label" for="condition{condition.hash}"> + <f:if condition="{displayConstantSubstitutions} && {condition.originalValue}"> + <f:then> + <span class="font-monospace">[{condition.value}]</span> + <span class="diff-item-result diff-item-result-inline font-monospace p-0"> + <f:format.raw> + <f:translate + key="LLL:EXT:backend/Resources/Private/Language/locallang_pagetsconfig.xlf:module.pagetsconfig_active.panel.info.conditionWithConstant" + arguments="{ + 0: '{backend:typoScript.fineDiff(from: condition.originalValue, to: condition.value)}' + }" + /> + </f:format.raw> + </span> + </f:then> + <f:else> + <span class="font-monospace">[{condition.value}]</span> + </f:else> + </f:if> + </label> </div> - </div> + </f:for> </form> </div> </div> diff --git a/typo3/sysext/backend/Resources/Private/Templates/PageTsConfig/Includes.html b/typo3/sysext/backend/Resources/Private/Templates/PageTsConfig/Includes.html index 1d53cf8714cb..70823655f610 100644 --- a/typo3/sysext/backend/Resources/Private/Templates/PageTsConfig/Includes.html +++ b/typo3/sysext/backend/Resources/Private/Templates/PageTsConfig/Includes.html @@ -7,7 +7,7 @@ <f:layout name="Module"/> -<f:section name="Content"> +<f:section name="Before"> <f:be.pageRenderer includeJavaScriptModules="{ 0: '@typo3/backend/context-menu.js', @@ -17,10 +17,14 @@ 4: '@typo3/backend/pagetsconfig/pagetsconfig-includes.js' }" /> - <f:variable name="args" value="{0: 'web', 1: pageUid}" /> - <typo3-immediate-action action="TYPO3.Backend.Storage.ModuleStateStorage.update" args="{args -> f:format.json() -> f:format.htmlspecialchars()}"></typo3-immediate-action> + <typo3-immediate-action + action="TYPO3.Backend.Storage.ModuleStateStorage.update" + args="{args -> f:format.json() -> f:format.htmlspecialchars()}" + ></typo3-immediate-action> +</f:section> +<f:section name="Content"> <h1> <f:translate key="LLL:EXT:backend/Resources/Private/Language/locallang_pagetsconfig.xlf:module.pagetsconfig_includes.headline" @@ -330,46 +334,42 @@ > <div class="panel-body"> <form action="{f:be.uri(route: 'pagetsconfig_includes', parameters: '{id: pageUid}')}" method="post"> - <div class="row"> - <div class="col-12"> - <f:for each="{conditions}" as="condition"> - <input type="hidden" name="pageTsConfigConditions[{condition.hash}]" value="0" /> - <div class="form-check form-switch"> - <input - type="checkbox" - class="form-check-input" - name="pageTsConfigConditions[{condition.hash}]" - id="pageTsConfigCondition{condition.hash}" - value="1" - data-global-event="change" - data-action-submit="$form" - data-value-selector="input[name='pageTsConfigConditions[{condition.hash}]']" - {f:if(condition: condition.active, then:'checked="checked"')} - /> - <label class="form-check-label" for="pageTsConfigCondition{condition.hash}"> - <f:if condition="{condition.originalValue}"> - <f:then> - <span class="font-monospace">[{condition.value}]</span> - <span class="diff-item-result diff-item-result-inline font-monospace p-0"> - <f:format.raw> - <f:translate - key="LLL:EXT:backend/Resources/Private/Language/locallang_pagetsconfig.xlf:module.pagetsconfig_includes.panel.info.conditionWithConstant" - arguments="{ - 0: '{backend:typoScript.fineDiff(from: condition.originalValue, to: condition.value)}' - }" - /> - </f:format.raw> - </span> - </f:then> - <f:else> - <span class="font-monospace">[{condition.value}]</span> - </f:else> - </f:if> - </label> - </div> - </f:for> + <f:for each="{conditions}" as="condition"> + <input type="hidden" name="pageTsConfigConditions[{condition.hash}]" value="0" /> + <div class="form-check form-switch"> + <input + type="checkbox" + class="form-check-input" + name="pageTsConfigConditions[{condition.hash}]" + id="pageTsConfigCondition{condition.hash}" + value="1" + data-global-event="change" + data-action-submit="$form" + data-value-selector="input[name='pageTsConfigConditions[{condition.hash}]']" + {f:if(condition: condition.active, then:'checked="checked"')} + /> + <label class="form-check-label" for="pageTsConfigCondition{condition.hash}"> + <f:if condition="{condition.originalValue}"> + <f:then> + <span class="font-monospace">[{condition.value}]</span> + <span class="diff-item-result diff-item-result-inline font-monospace p-0"> + <f:format.raw> + <f:translate + key="LLL:EXT:backend/Resources/Private/Language/locallang_pagetsconfig.xlf:module.pagetsconfig_includes.panel.info.conditionWithConstant" + arguments="{ + 0: '{backend:typoScript.fineDiff(from: condition.originalValue, to: condition.value)}' + }" + /> + </f:format.raw> + </span> + </f:then> + <f:else> + <span class="font-monospace">[{condition.value}]</span> + </f:else> + </f:if> + </label> </div> - </div> + </f:for> </form> </div> </div> diff --git a/typo3/sysext/backend/Resources/Private/Templates/PageTsConfig/RecordsOverview.html b/typo3/sysext/backend/Resources/Private/Templates/PageTsConfig/RecordsOverview.html index a239fcf2b857..4e9bff9a2142 100644 --- a/typo3/sysext/backend/Resources/Private/Templates/PageTsConfig/RecordsOverview.html +++ b/typo3/sysext/backend/Resources/Private/Templates/PageTsConfig/RecordsOverview.html @@ -5,17 +5,21 @@ <f:layout name="Module"/> -<f:section name="Content"> - +<f:section name="Before"> <f:be.pageRenderer includeJavaScriptModules="{ 0: '@typo3/backend/context-menu.js', 1: '@typo3/backend/element/immediate-action-element.js' }" /> - <f:variable name="args" value="{0: 'web', 1: id}" /> - <typo3-immediate-action action="TYPO3.Backend.Storage.ModuleStateStorage.update" args="{args -> f:format.json() -> f:format.htmlspecialchars()}"></typo3-immediate-action> + <typo3-immediate-action + action="TYPO3.Backend.Storage.ModuleStateStorage.update" + args="{args -> f:format.json() -> f:format.htmlspecialchars()}" + ></typo3-immediate-action> +</f:section> + +<f:section name="Content"> <h1> <f:translate key="LLL:EXT:backend/Resources/Private/Language/locallang_pagetsconfig.xlf:module.pagetsconfig_pages.headline" /> diff --git a/typo3/sysext/backend/Resources/Private/Templates/RecordDownloadSettings.html b/typo3/sysext/backend/Resources/Private/Templates/RecordDownloadSettings.html index 43a4810d0c1d..89276e7498e4 100644 --- a/typo3/sysext/backend/Resources/Private/Templates/RecordDownloadSettings.html +++ b/typo3/sysext/backend/Resources/Private/Templates/RecordDownloadSettings.html @@ -9,18 +9,16 @@ id="downloadSettingsForm" > - <div class="row row-cols-auto"> - <div class="col-12"> - <h5><f:translate key="LLL:EXT:backend/Resources/Private/Language/locallang_download.xlf:downloadSettings.generalSettings"/></h5> - </div> - <div class="col"> - <p> - <strong><f:translate key="LLL:EXT:backend/Resources/Private/Language/locallang_download.xlf:downloadSettings.columnsToDownload"/></strong><br/> - <span class="text-body-secondary"> - <f:translate key="LLL:EXT:backend/Resources/Private/Language/locallang_download.xlf:downloadSettings.default" - arguments="{0: '{f:translate(key: \'LLL:EXT:backend/Resources/Private/Language/locallang_download.xlf:downloadSettings.selectedColumns\')}'}"/> - </span> - </p> + <h1 class="h3"><f:translate key="LLL:EXT:backend/Resources/Private/Language/locallang_download.xlf:downloadSettings.generalSettings"/></h1> + <div class="form-row"> + <div class="form-group"> + <label class="form-label"> + <f:translate key="LLL:EXT:backend/Resources/Private/Language/locallang_download.xlf:downloadSettings.columnsToDownload"/> + </label> + <div class="form-description"> + <f:translate key="LLL:EXT:backend/Resources/Private/Language/locallang_download.xlf:downloadSettings.default" + arguments="{0: '{f:translate(key: \'LLL:EXT:backend/Resources/Private/Language/locallang_download.xlf:downloadSettings.selectedColumns\')}'}"/> + </div> <div class="form-check form-switch"> <input type="checkbox" class="form-check-input" name="allColumns" value="1" data-empty-value="0" id="allColumns"> <label class="form-check-label" for="allColumns"> @@ -28,14 +26,14 @@ </label> </div> </div> - <div class="col"> - <p> - <strong><f:translate key="LLL:EXT:backend/Resources/Private/Language/locallang_download.xlf:downloadSettings.valueFormat"/></strong><br/> - <span class="text-body-secondary"> - <f:translate key="LLL:EXT:backend/Resources/Private/Language/locallang_download.xlf:downloadSettings.default" - arguments="{0: '{f:translate(key: \'LLL:EXT:backend/Resources/Private/Language/locallang_download.xlf:downloadSettings.processedValues\')}'}"/> - </span> - </p> + <div class="form-group"> + <label class="form-label"> + <f:translate key="LLL:EXT:backend/Resources/Private/Language/locallang_download.xlf:downloadSettings.valueFormat"/> + </label> + <div class="form-description"> + <f:translate key="LLL:EXT:backend/Resources/Private/Language/locallang_download.xlf:downloadSettings.default" + arguments="{0: '{f:translate(key: \'LLL:EXT:backend/Resources/Private/Language/locallang_download.xlf:downloadSettings.processedValues\')}'}"/> + </div> <div class="form-check form-switch"> <input type="checkbox" class="form-check-input" name="rawValues" value="1" data-empty-value="0" id="rawValues"/> <label class="form-check-label" for="rawValues"> @@ -43,17 +41,14 @@ </label> </div> </div> - </div> - - <div class="row row-cols-auto mt-2"> - <div class="col"> - <label for="filename"> + <div class="form-group"> + <label class="form-label" for="filename"> <strong><f:translate key="LLL:EXT:backend/Resources/Private/Language/locallang_download.xlf:downloadSettings.filename"/></strong> </label> <input type="text" id="filename" placeholder="{f:translate(key: 'LLL:EXT:backend/Resources/Private/Language/locallang_download.xlf:downloadSettings.filename.placeholder', arguments: '{0: table}')}" class="form-control" name="filename" size="30"> </div> - <div class="col"> - <label for="format"> + <div class="form-group"> + <label class="form-label" for="format"> <strong><f:translate key="LLL:EXT:backend/Resources/Private/Language/locallang_download.xlf:downloadSettings.format"/></strong> </label> <select class="form-select t3js-record-download-format-selector" id="format" name="format"> @@ -66,22 +61,22 @@ <f:if condition="{formatOptions}"> <f:for each="{formatOptions}" key="formatName" as="format" iteration="i"> - <div class="row row-cols-auto mt-4 {f:if(condition: '!{i.isFirst}', then: 'hide')} t3js-record-download-format-option" data-formatName="{formatName}"> - <div class="col-12"> - <h5><f:translate key="LLL:EXT:backend/Resources/Private/Language/locallang_download.xlf:downloadSettings.formatOptions.{formatName}"/></h5> + <div class="{f:if(condition: '!{i.isFirst}', then: 'hide')} t3js-record-download-format-option" data-formatName="{formatName}"> + <h2 class="h3 headline-spaced"><f:translate key="LLL:EXT:backend/Resources/Private/Language/locallang_download.xlf:downloadSettings.formatOptions.{formatName}"/></h2> + <div class="form-row mb-0"> + <f:for each="{format.options}" key="formatOptionName" as="formatOption"> + <div class="form-group"> + <label class="form-label" for="{formatName}-{formatOptionName}"> + <f:translate key="LLL:EXT:backend/Resources/Private/Language/locallang_download.xlf:downloadSettings.formatOptions.{formatName}.{formatOptionName}"/> + </label> + <select class="form-select" id="{formatName}-{formatOptionName}" name="{formatName}[{formatOptionName}]"> + <f:for each="{formatOption}" key="optionName" as="option"> + <option value="{option}" {f:if(condition: '{format.defaults.{formatOptionName}} == {option}', then: 'selected')}>{option} ({f:translate(key: 'LLL:EXT:backend/Resources/Private/Language/locallang_download.xlf:downloadSettings.formatOptions.{formatName}.{formatOptionName}.{optionName}')})</option> + </f:for> + </select> + </div> + </f:for> </div> - <f:for each="{format.options}" key="formatOptionName" as="formatOption"> - <div class="col"> - <label for="{formatName}-{formatOptionName}"> - <strong><f:translate key="LLL:EXT:backend/Resources/Private/Language/locallang_download.xlf:downloadSettings.formatOptions.{formatName}.{formatOptionName}"/></strong> - </label> - <select class="form-select" id="{formatName}-{formatOptionName}" name="{formatName}[{formatOptionName}]"> - <f:for each="{formatOption}" key="optionName" as="option"> - <option value="{option}" {f:if(condition: '{format.defaults.{formatOptionName}} == {option}', then: 'selected')}>{option} ({f:translate(key: 'LLL:EXT:backend/Resources/Private/Language/locallang_download.xlf:downloadSettings.formatOptions.{formatName}.{formatOptionName}.{optionName}')})</option> - </f:for> - </select> - </div> - </f:for> </div> </f:for> </f:if> diff --git a/typo3/sysext/backend/Resources/Private/Templates/RecordList.html b/typo3/sysext/backend/Resources/Private/Templates/RecordList.html index 3c02a8ee51a1..09f3cedb277d 100644 --- a/typo3/sysext/backend/Resources/Private/Templates/RecordList.html +++ b/typo3/sysext/backend/Resources/Private/Templates/RecordList.html @@ -5,8 +5,7 @@ <f:layout name="Module" /> -<f:section name="Content"> - +<f:section name="Before"> <f:be.pageRenderer includeJavaScriptModules="{ 0: '@typo3/backend/recordlist.js', @@ -23,10 +22,14 @@ 11: '@typo3/backend/element/editable-page-title.js' }" /> - <f:variable name="immediateActionArgs" value="{0: 'web', 1: pageId}" /> - <typo3-immediate-action action="TYPO3.Backend.Storage.ModuleStateStorage.update" args="{immediateActionArgs -> f:format.json() -> f:format.htmlspecialchars()}"></typo3-immediate-action> + <typo3-immediate-action + action="TYPO3.Backend.Storage.ModuleStateStorage.update" + args="{immediateActionArgs -> f:format.json() -> f:format.htmlspecialchars()}" + ></typo3-immediate-action> +</f:section> +<f:section name="Content"> <typo3-backend-editable-page-title pageTitle="{pageTitle}" pageId="{pageId}" @@ -34,7 +37,6 @@ > {pageTitle} </typo3-backend-editable-page-title> - <f:format.raw>{additionalContentTop}</f:format.raw> <f:format.raw>{languageSelectorHtml}</f:format.raw> <f:format.raw>{searchBoxHtml}</f:format.raw> diff --git a/typo3/sysext/backend/Resources/Private/Templates/SiteConfiguration/Overview.html b/typo3/sysext/backend/Resources/Private/Templates/SiteConfiguration/Overview.html index 973584ff844a..78e2c76bd976 100644 --- a/typo3/sysext/backend/Resources/Private/Templates/SiteConfiguration/Overview.html +++ b/typo3/sysext/backend/Resources/Private/Templates/SiteConfiguration/Overview.html @@ -172,7 +172,7 @@ <f:if condition="{unassignedSites}"> <h2>{f:translate(key: 'LLL:EXT:backend/Resources/Private/Language/locallang_siteconfiguration.xlf:overview.unassignedSites.title')}</h2> - <p class="mb-3">{f:translate(key: 'LLL:EXT:backend/Resources/Private/Language/locallang_siteconfiguration.xlf:overview.unassignedSites.description')}</p> + <p>{f:translate(key: 'LLL:EXT:backend/Resources/Private/Language/locallang_siteconfiguration.xlf:overview.unassignedSites.description')}</p> <div class="table-fit"> <table class="table table-striped table-hover"> diff --git a/typo3/sysext/backend/Resources/Public/Css/backend.css b/typo3/sysext/backend/Resources/Public/Css/backend.css index 2a3448205832..b0a74adb30fb 100644 --- a/typo3/sysext/backend/Resources/Public/Css/backend.css +++ b/typo3/sysext/backend/Resources/Public/Css/backend.css @@ -20,17 +20,17 @@ } body{margin:0;font-family:var(--bs-body-font-family);font-size:var(--bs-body-font-size);font-weight:var(--bs-body-font-weight);line-height:var(--bs-body-line-height);color:var(--bs-body-color);text-align:var(--bs-body-text-align);background-color:var(--bs-body-bg);-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent} hr{margin:1rem 0;color:inherit;border:0;border-top:var(--bs-border-width) solid;opacity:1} -.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6,typo3-backend-editable-page-title{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.1;color:var(--bs-heading-color,inherit)} -.h1,h1,typo3-backend-editable-page-title{font-size:calc(1.29375rem + .525vw)} +.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6,typo3-backend-editable-page-title{margin-top:0;margin-bottom:calc(var(--typo3-spacing)/ 2);font-weight:500;line-height:1.2;color:var(--bs-heading-color,inherit)} +.h1,h1,typo3-backend-editable-page-title{font-size:calc(1.3rem + .6vw)} @media (min-width:1200px){ -.h1,h1,typo3-backend-editable-page-title{font-size:1.6875rem} +.h1,h1,typo3-backend-editable-page-title{font-size:1.75rem} } -.h2,h2{font-size:1.2rem} -.h3,h3{font-size:1.05rem} -.h4,h4{font-size:.9375rem} +.h2,h2{font-size:1.25rem} +.h3,h3{font-size:1rem} +.h4,h4{font-size:.875rem} .h5,h5{font-size:.9375rem} .h6,h6{font-size:.75rem} -p{margin-top:0;margin-bottom:.5rem} +p{margin-top:0;margin-bottom:var(--typo3-spacing)} abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none} address{margin-bottom:1rem;font-style:normal;line-height:inherit} ol,ul{padding-left:2rem} @@ -92,27 +92,27 @@ summary{display:list-item;cursor:pointer} progress{vertical-align:baseline} [hidden]{display:none!important} .lead{font-size:.9375rem;font-weight:300} -.display-1{font-size:calc(1.625rem + 4.5vw);font-weight:300;line-height:1.1} +.display-1{font-size:calc(1.625rem + 4.5vw);font-weight:300;line-height:1.2} @media (min-width:1200px){ .display-1{font-size:5rem} } -.display-2{font-size:calc(1.575rem + 3.9vw);font-weight:300;line-height:1.1} +.display-2{font-size:calc(1.575rem + 3.9vw);font-weight:300;line-height:1.2} @media (min-width:1200px){ .display-2{font-size:4.5rem} } -.display-3{font-size:calc(1.525rem + 3.3vw);font-weight:300;line-height:1.1} +.display-3{font-size:calc(1.525rem + 3.3vw);font-weight:300;line-height:1.2} @media (min-width:1200px){ .display-3{font-size:4rem} } -.display-4{font-size:calc(1.475rem + 2.7vw);font-weight:300;line-height:1.1} +.display-4{font-size:calc(1.475rem + 2.7vw);font-weight:300;line-height:1.2} @media (min-width:1200px){ .display-4{font-size:3.5rem} } -.display-5{font-size:calc(1.425rem + 2.1vw);font-weight:300;line-height:1.1} +.display-5{font-size:calc(1.425rem + 2.1vw);font-weight:300;line-height:1.2} @media (min-width:1200px){ .display-5{font-size:3rem} } -.display-6{font-size:calc(1.375rem + 1.5vw);font-weight:300;line-height:1.1} +.display-6{font-size:calc(1.375rem + 1.5vw);font-weight:300;line-height:1.2} @media (min-width:1200px){ .display-6{font-size:2.5rem} } @@ -1574,10 +1574,10 @@ to{transform:rotate(360deg)} .column-gap-4{-moz-column-gap:1.5rem!important;column-gap:1.5rem!important} .column-gap-5{-moz-column-gap:3rem!important;column-gap:3rem!important} .font-monospace{font-family:var(--bs-font-monospace)!important} -.fs-1{font-size:calc(1.29375rem + .525vw)!important} -.fs-2{font-size:1.2rem!important} -.fs-3{font-size:1.05rem!important} -.fs-4{font-size:.9375rem!important} +.fs-1{font-size:calc(1.3rem + .6vw)!important} +.fs-2{font-size:1.25rem!important} +.fs-3{font-size:1rem!important} +.fs-4{font-size:.875rem!important} .fs-5{font-size:.9375rem!important} .fs-6{font-size:.75rem!important} .fst-italic{font-style:italic!important} @@ -2644,7 +2644,7 @@ to{transform:rotate(360deg)} .text-xxl-center{text-align:center!important} } @media (min-width:1200px){ -.fs-1{font-size:1.6875rem!important} +.fs-1{font-size:1.75rem!important} } @media print{ .d-print-inline{display:inline!important} @@ -2819,11 +2819,15 @@ button[aria-expanded=true]:not(:disabled) .modulemenu-indicator:after{transform: .scaffold-modulemenu-expanded .modulemenu-action{margin-left:0;width:100%} .scaffold-modulemenu-expanded .modulemenu-indicator{display:block!important} .scaffold-modulemenu-expanded .modulemenu-name{position:static;margin:0 0 0 1em;width:auto;height:auto} -:root{--typo3-font-family-sans-serif:Verdana,Arial,Helvetica,sans-serif;--typo3-font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;--typo3-font-family:var(--typo3-font-family-sans-serif);--typo3-font-family-code:var(--typo3-font-family-monospace);--typo3-spacing:1rem;--typo3-header-font-family:"Source Sans 3",sans-serif;--typo3-light-color:#000;--typo3-light-secondary-color:#666666;--typo3-light-bg:#fff;--typo3-light-border-color:rgb(215, 215, 215);--typo3-light-link-color:#0078e6;--typo3-light-link-hover-color:#1a86e9;--typo3-light-hover-color:var(--typo3-light-color);--typo3-light-hover-bg:#f2f8fe;--typo3-light-hover-border-color:#d9ebfb;--typo3-light-focus-color:var(--typo3-light-color);--typo3-light-focus-bg:#f2f8fe;--typo3-light-focus-border-color:#3393eb;--typo3-light-active-color:#fff;--typo3-light-active-bg:#3393eb;--typo3-light-active-border-color:#3393eb;--typo3-light-disabled-color:rgb(115, 115, 115);--typo3-light-disabled-bg:transparent;--typo3-light-disabled-border-color:transparent;--typo3-dark-color:#fff;--typo3-dark-secondary-color:#999999;--typo3-dark-bg:rgb(30, 30, 30);--typo3-dark-border-color:rgb(51, 51, 51);--typo3-dark-link-color:#66aef0;--typo3-dark-link-hover-color:#80bcf3;--typo3-dark-hover-color:var(--typo3-dark-color);--typo3-dark-hover-bg:rgb(51, 51, 51);--typo3-dark-hover-border-color:rgb(90, 90, 90);--typo3-dark-focus-color:var(--typo3-dark-color);--typo3-dark-focus-bg:#003c73;--typo3-dark-focus-border-color:#00488a;--typo3-dark-active-color:#fff;--typo3-dark-active-bg:#0066c4;--typo3-dark-active-border-color:#0060b8;--typo3-dark-disabled-color:rgb(115, 115, 115);--typo3-dark-disabled-bg:transparent;--typo3-dark-disabled-border-color:transparent;--typo3-component-color:var(--typo3-light-color);--typo3-component-secondary-color:var(--typo3-light-secondary-color);--typo3-component-bg:var(--typo3-light-bg);--typo3-component-link-color:var(--typo3-light-link-color);--typo3-component-link-hover-color:var(--typo3-light-link-hover-color);--typo3-component-font-size:12px;--typo3-component-line-height:1.5;--typo3-component-border-radius:4px;--typo3-component-border-width:1px;--typo3-component-border-color:var(--typo3-light-border-color);--typo3-component-padding-y:.75rem;--typo3-component-padding-x:1rem;--typo3-component-box-shadow:0 1px 2px rgba(0, 0, 0, .25);--typo3-component-hover-color:var(--typo3-light-hover-color);--typo3-component-hover-bg:var(--typo3-light-hover-bg);--typo3-component-hover-border-color:var(--typo3-light-hover-border-color);--typo3-component-focus-color:var(--typo3-light-focus-color);--typo3-component-focus-bg:var(--typo3-light-focus-bg);--typo3-component-focus-border-color:var(--typo3-light-focus-border-color);--typo3-component-active-color:var(--typo3-light-active-color);--typo3-component-active-bg:var(--typo3-light-active-bg);--typo3-component-active-border-color:var(--typo3-light-active-border-color);--typo3-component-disabled-color:var(--typo3-light-disabled-color);--typo3-component-disabled-bg:var(--typo3-light-disabled-bg);--typo3-component-disabled-border-color:var(--typo3-light-disabled-border-color);--typo3-component-spacing:1.5rem;--typo3-list-item-padding-y:.5rem;--typo3-list-item-padding-x:.75rem;--typo3-list-item-hover-color:var(--typo3-component-hover-color);--typo3-list-item-hover-bg:var(--typo3-component-hover-bg);--typo3-list-item-hover-border-color:var(--typo3-component-hover-border-color);--typo3-list-item-focus-color:var(--typo3-component-focus-color);--typo3-list-item-focus-bg:var(--typo3-component-focus-bg);--typo3-list-item-focus-border-color:var(--typo3-component-focus-border-color);--typo3-list-item-active-color:var(--typo3-list-item-focus-color);--typo3-list-item-active-bg:var(--typo3-list-item-focus-bg);--typo3-list-item-active-border-color:var(--typo3-list-item-focus-border-color);--typo3-list-item-disabled-color:var(--typo3-component-disabled-color);--typo3-list-item-disabled-bg:var(--typo3-component-disabled-bg);--typo3-list-item-disabled-border-color:var(--typo3-component-disabled-border-color);--typo3-input-color:#333;--typo3-input-bg:#fefefe;--typo3-input-border-width:var(--bs-border-width);--typo3-input-border-color:rgb(187, 187, 187);--typo3-input-border-radius:0.125rem;--typo3-input-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.075);--typo3-input-focus-color:#333;--typo3-input-focus-bg:#fefefe;--typo3-input-focus-border-color:#80bcf3;--typo3-input-focus-box-shadow:0 0 0 0.25rem rgba(0, 120, 230, 0.25);--typo3-input-disabled-bg:var(--bs-secondary-bg)} +:root{--typo3-font-family-sans-serif:Verdana,Arial,Helvetica,sans-serif;--typo3-font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;--typo3-font-family:var(--typo3-font-family-sans-serif);--typo3-font-family-code:var(--typo3-font-family-monospace);--typo3-spacing:1rem;--typo3-header-font-family:"Source Sans 3",sans-serif;--typo3-light-color:#000;--typo3-light-secondary-color:#666666;--typo3-light-bg:#fff;--typo3-light-border-color:rgb(215, 215, 215);--typo3-light-link-color:#0078e6;--typo3-light-link-hover-color:#1a86e9;--typo3-light-hover-color:var(--typo3-light-color);--typo3-light-hover-bg:#f2f8fe;--typo3-light-hover-border-color:#d9ebfb;--typo3-light-focus-color:var(--typo3-light-color);--typo3-light-focus-bg:#f2f8fe;--typo3-light-focus-border-color:#3393eb;--typo3-light-active-color:#fff;--typo3-light-active-bg:#3393eb;--typo3-light-active-border-color:#3393eb;--typo3-light-disabled-color:rgb(115, 115, 115);--typo3-light-disabled-bg:transparent;--typo3-light-disabled-border-color:transparent;--typo3-dark-color:#fff;--typo3-dark-secondary-color:#999999;--typo3-dark-bg:rgb(30, 30, 30);--typo3-dark-border-color:rgb(51, 51, 51);--typo3-dark-link-color:#66aef0;--typo3-dark-link-hover-color:#80bcf3;--typo3-dark-hover-color:var(--typo3-dark-color);--typo3-dark-hover-bg:rgb(51, 51, 51);--typo3-dark-hover-border-color:rgb(90, 90, 90);--typo3-dark-focus-color:var(--typo3-dark-color);--typo3-dark-focus-bg:#003c73;--typo3-dark-focus-border-color:#00488a;--typo3-dark-active-color:#fff;--typo3-dark-active-bg:#0066c4;--typo3-dark-active-border-color:#0060b8;--typo3-dark-disabled-color:rgb(115, 115, 115);--typo3-dark-disabled-bg:transparent;--typo3-dark-disabled-border-color:transparent;--typo3-component-color:var(--typo3-light-color);--typo3-component-secondary-color:var(--typo3-light-secondary-color);--typo3-component-bg:var(--typo3-light-bg);--typo3-component-link-color:var(--typo3-light-link-color);--typo3-component-link-hover-color:var(--typo3-light-link-hover-color);--typo3-component-font-size:12px;--typo3-component-line-height:1.5;--typo3-component-border-radius:4px;--typo3-component-border-width:1px;--typo3-component-border-color:var(--typo3-light-border-color);--typo3-component-padding-y:.75rem;--typo3-component-padding-x:1rem;--typo3-component-box-shadow:0 1px 2px rgba(0, 0, 0, .25);--typo3-component-hover-color:var(--typo3-light-hover-color);--typo3-component-hover-bg:var(--typo3-light-hover-bg);--typo3-component-hover-border-color:var(--typo3-light-hover-border-color);--typo3-component-focus-color:var(--typo3-light-focus-color);--typo3-component-focus-bg:var(--typo3-light-focus-bg);--typo3-component-focus-border-color:var(--typo3-light-focus-border-color);--typo3-component-active-color:var(--typo3-light-active-color);--typo3-component-active-bg:var(--typo3-light-active-bg);--typo3-component-active-border-color:var(--typo3-light-active-border-color);--typo3-component-disabled-color:var(--typo3-light-disabled-color);--typo3-component-disabled-bg:var(--typo3-light-disabled-bg);--typo3-component-disabled-border-color:var(--typo3-light-disabled-border-color);--typo3-component-spacing:2rem;--typo3-list-item-padding-y:.5rem;--typo3-list-item-padding-x:.75rem;--typo3-list-item-hover-color:var(--typo3-component-hover-color);--typo3-list-item-hover-bg:var(--typo3-component-hover-bg);--typo3-list-item-hover-border-color:var(--typo3-component-hover-border-color);--typo3-list-item-focus-color:var(--typo3-component-focus-color);--typo3-list-item-focus-bg:var(--typo3-component-focus-bg);--typo3-list-item-focus-border-color:var(--typo3-component-focus-border-color);--typo3-list-item-active-color:var(--typo3-list-item-focus-color);--typo3-list-item-active-bg:var(--typo3-list-item-focus-bg);--typo3-list-item-active-border-color:var(--typo3-list-item-focus-border-color);--typo3-list-item-disabled-color:var(--typo3-component-disabled-color);--typo3-list-item-disabled-bg:var(--typo3-component-disabled-bg);--typo3-list-item-disabled-border-color:var(--typo3-component-disabled-border-color);--typo3-input-color:#333;--typo3-input-bg:#fefefe;--typo3-input-border-width:var(--bs-border-width);--typo3-input-border-color:rgb(187, 187, 187);--typo3-input-border-radius:0.125rem;--typo3-input-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.075);--typo3-input-focus-color:#333;--typo3-input-focus-bg:#fefefe;--typo3-input-focus-border-color:#80bcf3;--typo3-input-focus-box-shadow:0 0 0 0.25rem rgba(0, 120, 230, 0.25);--typo3-input-disabled-bg:var(--bs-secondary-bg)} @media (prefers-color-scheme:dark){ :root{--typo3-component-color:var(--typo3-dark-color);--typo3-component-secondary-color:var(--typo3-dark-secondary-color);--typo3-component-bg:var(--typo3-dark-bg);--typo3-component-border-color:var(--typo3-dark-border-color);--typo3-component-link-color:var(--typo3-dark-link-color);--typo3-component-link-hover-color:var(--typo3-dark-link-hover-color);--typo3-component-hover-color:var(--typo3-dark-hover-color);--typo3-component-hover-bg:var(--typo3-dark-hover-bg);--typo3-component-hover-border-color:var(--typo3-dark-hover-border-color);--typo3-component-focus-color:var(--typo3-dark-focus-color);--typo3-component-focus-bg:var(--typo3-dark-focus-bg);--typo3-component-focus-border-color:var(--typo3-dark-focus-border-color);--typo3-component-active-color:var(--typo3-dark-active-color);--typo3-component-active-bg:var(--typo3-dark-active-bg);--typo3-component-active-border-color:var(--typo3-dark-active-border-color);--typo3-component-disabled-color:var(--typo3-dark-disabled-color);--typo3-component-disabled-bg:var(--typo3-dark-disabled-bg);--typo3-component-disabled-border-color:var(--typo3-dark-disabled-border-color)} } .dropdown-menu{--bs-secondary-color:var(--typo3-component-secondary-color)} +.h1,h1,typo3-backend-editable-page-title{font-family:var(--typo3-header-font-family);font-variant:normal;font-weight:400} +.h1:not(:first-child):not([class]),.h2:not(:first-child):not([class]),.h3:not(:first-child):not([class]),.headline-spaced.h1,.headline-spaced.h2,.headline-spaced.h3,h1.headline-spaced,h1:not(:first-child):not([class]),h2.headline-spaced,h2:not(:first-child):not([class]),h3.headline-spaced,h3:not(:first-child):not([class]),typo3-backend-editable-page-title.headline-spaced,typo3-backend-editable-page-title:not(:first-child):not([class]){margin-top:calc(var(--typo3-spacing) * 2)} +.h1,.h2,.h3,.h4,.h5,.h6{font-family:inherit} +hr.spacer{border-top:none;margin-top:var(--typo3-spacing);margin-bottom:var(--typo3-spacing)} .alert a{color:inherit;text-decoration:underline} .alert-title{font-size:1.12em;font-weight:700;margin:0 0 .25em} .alert-body,.alert-message{margin:0;font-size:.9em} @@ -2893,7 +2897,10 @@ typo3-backend-formengine-suggest-result-item .formengine-suggest-result-item-lab .btn-borderless{--bs-btn-bg:transparent;--bs-btn-border-color:transparent;--bs-btn-box-shadow:none;--bs-btn-padding-x:var(--bs-btn-padding-y)} .btn-permission{--bs-btn-bg:transparent;--bs-btn-border-color:transparent;--bs-btn-box-shadow:none;--bs-btn-padding-x:0;--bs-btn-padding-y:0} .table .btn:not(.btn-sm){--bs-btn-padding-x:var(--bs-btn-padding-y)} -pre[class*=language-]{margin-bottom:var(--typo3-component-spacing)} +code,pre{-webkit-hyphens:none;hyphens:none} +code[class*=language-],pre[class*=language-]{color:inherit;background:0 0;font-size:1em;text-align:start;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;hyphens:none} +pre[class*=language-]{border-radius:4px;padding:1em;overflow:auto;margin-bottom:var(--typo3-spacing)} +:not(pre)>code[class*=language-],pre[class*=language-]{background-color:rgba(0,0,0,.05)} .dropdown-menu{font-size:var(--typo3-component-font-size);line-height:var(--typo3-component-line-height);max-width:calc(100vw - 20px)} .dropdown-menu a:not([class]){color:var(--typo3-component-link-color)} .dropdown-menu a:not([class]):hover{color:var(--typo3-component-link-hover-color)} @@ -3005,7 +3012,7 @@ a.dropdown-toggle{text-decoration:none} .statusreport a:not([class]):hover{color:#0060b8;text-decoration:underline} .statusreport .statusreport-indicator-icon{position:relative;display:inline-flex;justify-content:center;align-items:center;color:var(--statusreport-icon-color);font-size:var(--statusreport-icon-size);height:var(--statusreport-icon-size);width:var(--statusreport-icon-size)} .statusreport .statusreport-indicator-icon:before{position:absolute;content:" ";top:50%;left:50%;height:calc(var(--statusreport-icon-size) * 1.5);width:calc(var(--statusreport-icon-size) * 1.5);background-color:var(--statusreport-icon-bg);transform:translate(-50%,-50%);border-radius:50%} -.statusreport-wrapper{border-radius:var(--statusreport-border-radius);box-shadow:var(--statusreport-box-shadow);margin-bottom:var(--typo3-component-spacing)} +.statusreport-wrapper{border-radius:var(--statusreport-border-radius);box-shadow:var(--statusreport-box-shadow);margin-bottom:var(--typo3-spacing)} .statusreport-wrapper .statusreport:first-child{border-top-left-radius:var(--statusreport-border-radius);border-top-right-radius:var(--statusreport-border-radius)} .statusreport-wrapper .statusreport:last-child{border-bottom-left-radius:var(--statusreport-border-radius);border-bottom-right-radius:var(--statusreport-border-radius)} .statusreport-wrapper .statusreport+.statusreport{margin-top:-1px} @@ -3053,16 +3060,15 @@ a.dropdown-toggle{text-decoration:none} .module-docheader .module-docheader-bar .form-group{margin:0} .module-docheader .module-docheader-bar-container{display:flex;gap:var(--module-docheader-spacing);flex-wrap:wrap} .module-body{padding:var(--module-body-padding)} -.module-body>.callout:first-child{margin-top:0} .module-body>.container{padding-left:0;padding-right:0} .module-body .container-small{max-width:768px;margin:0 auto} .module-body>:last-child{margin-bottom:0} :root{--panel-bg:#fff;--panel-border-color:#ccc;--panel-border-radius:var(--typo3-component-border-radius);--panel-border-width:var(--typo3-component-border-width);--panel-padding:var(--typo3-component-padding-x);--panel-header-padding-x:var(--typo3-component-padding-x);--panel-header-padding-y:var(--typo3-component-padding-y);--panel-spacing:var(--typo3-component-spacing);--panel-box-shadow:var(--typo3-component-box-shadow);--panel-primary-border-color:#99c9f5;--panel-primary-progress-bg:#0078e6;--panel-primary-heading-color:#000;--panel-primary-heading-bg:#d9ebfb;--panel-secondary-border-color:#c7c7c7;--panel-secondary-progress-bg:rgb(115, 115, 115);--panel-secondary-heading-color:#000;--panel-secondary-heading-bg:#eaeaea;--panel-success-border-color:#9fcb9f;--panel-success-progress-bg:#107c10;--panel-success-heading-color:#000;--panel-success-heading-bg:#dbebdb;--panel-info-border-color:#c5ddf3;--panel-info-progress-bg:#6daae0;--panel-info-heading-color:#000;--panel-info-heading-bg:#e9f2fa;--panel-warning-border-color:#f6dab1;--panel-warning-progress-bg:#e8a33d;--panel-warning-heading-color:#000;--panel-warning-heading-bg:#fcf1e2;--panel-danger-border-color:#e9b1b1;--panel-danger-progress-bg:#c83c3c;--panel-danger-heading-color:#000;--panel-danger-heading-bg:#f7e2e2;--panel-light-border-color:#c4c4c4;--panel-light-progress-bg:gainsboro;--panel-light-heading-color:#000;--panel-light-heading-bg:whitesmoke;--panel-default-border-color:#c4c4c4;--panel-default-progress-bg:gainsboro;--panel-default-heading-color:#000;--panel-default-heading-bg:whitesmoke;--panel-notice-border-color:#adadad;--panel-notice-progress-bg:rgb(51, 51, 51);--panel-notice-heading-color:#000;--panel-notice-heading-bg:#e0e0e0;--panel-dark-border-color:#a5a5a5;--panel-dark-progress-bg:rgb(30, 30, 30);--panel-dark-heading-color:#000;--panel-dark-heading-bg:#dddddd} -.panel-group{display:flex;flex-flow:column;overflow:hidden;margin-bottom:var(--panel-spacing);border-radius:var(--panel-border-radius);box-shadow:var(--panel-box-shadow)} +.panel-group{display:flex;flex-flow:column;overflow:hidden;margin-bottom:var(--typo3-spacing);border-radius:var(--panel-border-radius);box-shadow:var(--panel-box-shadow)} .panel-group>.panel{border-radius:0;margin-bottom:0;box-shadow:none;margin-top:calc(var(--panel-border-width) * -1)} .panel-group>.panel:first-child{margin-top:0;border-top-left-radius:var(--panel-border-radius);border-top-right-radius:var(--panel-border-radius)} .panel-group>.panel:last-child{border-bottom-left-radius:var(--panel-border-radius);border-bottom-right-radius:var(--panel-border-radius)} -.panel{display:flex;flex-direction:column;overflow:hidden;min-width:0;word-wrap:break-word;background-clip:border-box;background-color:var(--panel-bg);border:var(--panel-border-width) solid var(--panel-border-color);border-radius:var(--panel-border-radius);box-shadow:var(--panel-box-shadow);margin-bottom:var(--panel-spacing);transition:all .2s ease-in-out;transition-property:box-shadow,border,transform} +.panel{display:flex;flex-direction:column;overflow:hidden;min-width:0;word-wrap:break-word;background-clip:border-box;background-color:var(--panel-bg);border:var(--panel-border-width) solid var(--panel-border-color);border-radius:var(--panel-border-radius);box-shadow:var(--panel-box-shadow);margin-bottom:var(--typo3-spacing);transition:all .2s ease-in-out;transition-property:box-shadow,border,transform} .panel .table-fit{box-shadow:none;border-radius:0;border-left:0;border-right:0;border-bottom:0;margin-bottom:0} .panel-loader{padding:var(--panel-padding)} .panel-progress{display:none;position:absolute;top:0;left:0;height:3px;width:100%;z-index:1;background-color:transparent} @@ -3126,10 +3132,11 @@ a.dropdown-toggle{text-decoration:none} .form-check.form-check-type-icon-toggle .form-check-input:checked~.form-check-label .form-check-label-icon-checked{display:block} .form-check.form-check-type-icon-toggle .form-check-input:checked~.form-check-label .form-check-label-icon-unchecked{display:none} .form-check.form-check-type-icon-toggle .form-check-label{margin-top:.35em} -.form-check.form-check-type-toggle{display:inline-block;color:rgba(0,0,0,.25);padding-left:0;margin:0} +.form-check.form-check-type-toggle{display:inline-block;padding-left:0;margin:0} .form-check.form-check-type-toggle .form-check-input[type=checkbox]{margin:0;margin-top:1px;float:none;border:0;width:1.3333333333em;height:1.3333333333em;background-size:contain;background-image:url("data:image/svg+xml, %3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cg class='icon-color'%3e%3cpath d='M13 2c.6 0 1 .4 1 1v10c0 .6-.4 1-1 1H3c-.6 0-1-.4-1-1V3c0-.6.4-1 1-1h10m0-1H3c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h10c1.1 0 2-.9 2-2V3c0-1.1-.9-2-2-2z'/%3e%3c/g%3e%3c/svg%3e")} .form-check.form-check-type-toggle .form-check-input[type=checkbox]:active{filter:brightness(100%)} .form-check.form-check-type-toggle .form-check-input[type=checkbox]:checked{background-image:url("data:image/svg+xml, %3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cg class='icon-color'%3e%3cpath d='M12.1 5.3l-.4-.3c-.1-.1-.3-.1-.4 0L6.6 9.8l-2-2c-.1-.1-.3-.1-.4 0l-.3.4c-.1.1-.1.3 0 .4L6 10.7l.4.3c.1.1.3.1.4 0l.4-.4 4.9-4.9c.1-.1.1-.3 0-.4z'/%3e%3cpath d='M13 2c.6 0 1 .4 1 1v10c0 .6-.4 1-1 1H3c-.6 0-1-.4-1-1V3c0-.6.4-1 1-1h10m0-1H3c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h10c1.1 0 2-.9 2-2V3c0-1.1-.9-2-2-2z'/%3e%3c/g%3e%3c/svg%3e");background-color:#fff} +.form-check.form-check-size-input{margin-top:7px;margin-bottom:7px} .simpletable{padding:0;margin-bottom:1.5em} .simpletable td,.simpletable th{padding:.25em 1em} .simpletable td:first-child,.simpletable th:first-child{padding-left:0} @@ -3534,7 +3541,7 @@ to{opacity:1;transform:translate3d(0,0,0)} .table-transparent{--bs-table-bg:transparent} .table-vertical-top td,.table-vertical-top th{vertical-align:top!important} .table-center td,.table-center th{text-align:center!important} -.table-fit{width:100%;border-radius:var(--typo3-component-border-radius);box-shadow:var(--typo3-component-box-shadow);margin-bottom:var(--typo3-component-spacing);overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ccc} +.table-fit{width:100%;border-radius:var(--typo3-component-border-radius);box-shadow:var(--typo3-component-box-shadow);margin-bottom:var(--typo3-spacing);overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ccc} .table-fit .table-bordered>:not(caption)>*{border-width:0} .table-fit .table-bordered>:not(caption)>*>*{border-top:0;border-width:var(--bs-border-width)} .table-fit caption{border-top:var(--bs-border-width) solid #ccc;padding-left:var(--typo3-component-padding-x);padding-right:var(--typo3-component-padding-x)} @@ -3614,9 +3621,9 @@ to{opacity:1;transform:translate3d(0,0,0)} .modal-multi-step-wizard .modal-footer .btn+.btn{margin-left:.5em} .modal-multi-step-wizard .modal-footer .progress-bar.inactive{background:0 0;color:#000} :root{--note-primary-color:#000;--note-primary-bg:#d9ebfb;--note-primary-header-color:#000;--note-primary-header-bg:#99c9f5;--note-secondary-color:#000;--note-secondary-bg:#eaeaea;--note-secondary-header-color:#000;--note-secondary-header-bg:#c7c7c7;--note-success-color:#000;--note-success-bg:#dbebdb;--note-success-header-color:#000;--note-success-header-bg:#9fcb9f;--note-info-color:#000;--note-info-bg:#e9f2fa;--note-info-header-color:#000;--note-info-header-bg:#c5ddf3;--note-warning-color:#000;--note-warning-bg:#fcf1e2;--note-warning-header-color:#000;--note-warning-header-bg:#f6dab1;--note-danger-color:#000;--note-danger-bg:#f7e2e2;--note-danger-header-color:#000;--note-danger-header-bg:#e9b1b1;--note-light-color:#000;--note-light-bg:#fefefe;--note-light-header-color:#000;--note-light-header-bg:#fbfbfb;--note-default-color:#000;--note-default-bg:#fefefe;--note-default-header-color:#000;--note-default-header-bg:#fbfbfb;--note-notice-color:#000;--note-notice-bg:#e0e0e0;--note-notice-header-color:#000;--note-notice-header-bg:#adadad;--note-dark-color:#000;--note-dark-bg:#dddddd;--note-dark-header-color:#000;--note-dark-header-bg:#a5a5a5;--note-light-bg:rgb(245, 245, 245);--note-light-header-bg:#dddddd;--note-default-bg:rgb(238, 238, 238);--note-default-header-bg:#d6d6d6} -.note-list{display:grid;gap:calc(var(--typo3-component-spacing)/ 2);margin-bottom:var(--typo3-component-spacing)} +.note-list{display:grid;gap:var(--typo3-spacing);margin-bottom:var(--typo3-spacing)} .note-list .note{margin-bottom:0} -.note{overflow:hidden;position:relative;z-index:1;color:var(--note-color);background-color:var(--note-bg);border-radius:var(--typo3-component-border-radius);margin-bottom:var(--typo3-component-spacing);box-shadow:var(--typo3-component-box-shadow);--note-color:var(--note-default-color);--note-bg:var(--note-default-bg);--note-header-color:var(--note-default-header-color);--note-header-bg:var(--note-default-header-bg)} +.note{overflow:hidden;position:relative;z-index:1;color:var(--note-color);background-color:var(--note-bg);border-radius:var(--typo3-component-border-radius);margin-bottom:var(--typo3-spacing);box-shadow:var(--typo3-component-box-shadow);--note-color:var(--note-default-color);--note-bg:var(--note-default-bg);--note-header-color:var(--note-default-header-color);--note-header-bg:var(--note-default-header-bg)} .note-header{color:var(--note-header-color);background-color:var(--note-header-bg);padding:.5rem 1rem} .note-header-bar{display:flex;align-items:center;flex-wrap:wrap;gap:.5rem} .note-actions{margin-left:auto} @@ -3663,8 +3670,8 @@ a.card:hover{--typo3-card-border-color:var(--typo3-card-hover-border-color);text } .card-body,.card-footer,.card-header,.card-image{padding:var(--typo3-card-padding) var(--typo3-card-padding) 0 var(--typo3-card-padding)} .card-body:last-child,.card-footer:last-child,.card-header:last-child,.card-image:last-child{padding-bottom:var(--typo3-card-padding)} -.card-body :first-child,.card-footer :first-child,.card-header :first-child,.card-image :first-child{margin-top:0} -.card-body :last-child,.card-footer :last-child,.card-header :last-child,.card-image :last-child{margin-bottom:0} +.card-body>:first-child:not(.row),.card-footer>:first-child:not(.row),.card-header>:first-child:not(.row),.card-image>:first-child:not(.row){margin-top:0} +.card-body>:last-child,.card-footer>:last-child,.card-header>:last-child,.card-image>:last-child{margin-bottom:0} .card-image{position:relative;padding-left:0;padding-right:0} .card-image:first-child{padding-top:0} .card-image:first-child .card-image-badge{top:calc(var(--typo3-card-padding) * .5)} @@ -3689,9 +3696,38 @@ a.card:hover{--typo3-card-border-color:var(--typo3-card-hover-border-color);text .card-dark{--typo3-card-color:#000;--typo3-card-bg:#f4f4f4;--typo3-card-border-color:#a5a5a5;--typo3-card-hover-border-color:#787878} .card-light{--typo3-card-color:#000;--typo3-card-bg:rgb(245, 245, 245);--typo3-card-border-color:#dddddd;--typo3-card-hover-border-color:#c4c4c4} .card-default{--typo3-card-color:#000;--typo3-card-bg:rgb(238, 238, 238);--typo3-card-border-color:#d6d6d6;--typo3-card-hover-border-color:#bebebe} -.form{margin-bottom:var(--typo3-component-spacing)} +.form{margin-bottom:var(--typo3-spacing)} +.form-row{display:flex;flex-wrap:wrap;gap:var(--typo3-spacing);margin-bottom:var(--typo3-spacing)} +.form-row>.form-group{margin-bottom:0} +.form-row>.form-group>[class*=form-row]{margin-bottom:0} +@media (min-width:576px){ +.form-row-sm{display:flex;flex-wrap:wrap;gap:var(--typo3-spacing);margin-bottom:var(--typo3-spacing)} +.form-row-sm>.form-group{margin-bottom:0} +.form-row-sm>.form-group>[class*=form-row]{margin-bottom:0} +} +@media (min-width:768px){ +.form-row-md{display:flex;flex-wrap:wrap;gap:var(--typo3-spacing);margin-bottom:var(--typo3-spacing)} +.form-row-md>.form-group{margin-bottom:0} +.form-row-md>.form-group>[class*=form-row]{margin-bottom:0} +} +@media (min-width:992px){ +.form-row-lg{display:flex;flex-wrap:wrap;gap:var(--typo3-spacing);margin-bottom:var(--typo3-spacing)} +.form-row-lg>.form-group{margin-bottom:0} +.form-row-lg>.form-group>[class*=form-row]{margin-bottom:0} +} +@media (min-width:1200px){ +.form-row-xl{display:flex;flex-wrap:wrap;gap:var(--typo3-spacing);margin-bottom:var(--typo3-spacing)} +.form-row-xl>.form-group{margin-bottom:0} +.form-row-xl>.form-group>[class*=form-row]{margin-bottom:0} +} +@media (min-width:1400px){ +.form-row-xxl{display:flex;flex-wrap:wrap;gap:var(--typo3-spacing);margin-bottom:var(--typo3-spacing)} +.form-row-xxl>.form-group{margin-bottom:0} +.form-row-xxl>.form-group>[class*=form-row]{margin-bottom:0} +} .form-label{word-break:break-all} .form-description{opacity:.75;margin-bottom:.5rem} +.form-label+.form-description{margin-top:-.25rem} .form-group{margin-bottom:var(--typo3-spacing)} .form-group-dashed+.form-group-dashed{padding-top:var(--typo3-spacing);border-top:1px dashed rgba(0,0,0,.15)} .form-wizard-icon-list{color:var(--typo3-component-color);background:var(--typo3-component-bg);border:var(--typo3-component-border-width) solid var(--typo3-component-border-color);border-radius:var(--bs-border-radius);margin-top:.25rem;padding:calc(var(--typo3-spacing)/ 4);display:flex;flex-wrap:wrap;gap:2px} @@ -3735,10 +3771,11 @@ typo3-backend-live-search-result-item-action>*,typo3-backend-live-search-result- typo3-backend-live-search-result-item-action>* .livesearch-result-item-icon,typo3-backend-live-search-result-item>* .livesearch-result-item-icon{display:flex;gap:.5em;flex-grow:0;flex-shrink:0;align-items:center} typo3-backend-live-search-result-item-action>* .livesearch-result-item-title,typo3-backend-live-search-result-item>* .livesearch-result-item-title{flex-grow:1;word-break:break-word} typo3-backend-live-search-result-item-action>* .livesearch-result-item-title .small,typo3-backend-live-search-result-item-action>* .livesearch-result-item-title small,typo3-backend-live-search-result-item>* .livesearch-result-item-title .small,typo3-backend-live-search-result-item>* .livesearch-result-item-title small{opacity:var(--livesearch-item-opacity)} -.recordlist{overflow:hidden;background:var(--panel-bg);box-shadow:var(--panel-box-shadow);border-radius:var(--panel-border-radius);border:var(--panel-border-width) solid var(--panel-default-border-color);margin-bottom:var(--panel-spacing)} +.recordlist{overflow:hidden;background:var(--panel-bg);box-shadow:var(--panel-box-shadow);border-radius:var(--panel-border-radius);border:var(--panel-border-width) solid var(--panel-default-border-color);margin-bottom:var(--typo3-spacing)} .recordlist table tr td.deletePlaceholder{text-decoration:line-through} .recordlist .table-fit{box-shadow:none;border-radius:0;border-left:0;border-right:0;border-bottom:0;margin-bottom:0} .recordlist .pagination{display:inline-flex} +.recordlist+.recordlist{margin-top:calc(var(--typo3-spacing) * 1.5)} .recordlist-heading{display:flex;align-items:center;flex-wrap:wrap;color:var(--panel-default-heading-color);background:var(--panel-default-heading-bg);padding:var(--panel-header-padding-y) var(--panel-header-padding-x);gap:var(--panel-header-padding-y) var(--panel-header-padding-x)} .recordlist-heading-row{flex-grow:1;display:flex;align-items:center;flex-wrap:wrap;max-width:100%;gap:var(--panel-header-padding-y) var(--panel-header-padding-x)} .recordlist-heading-title{font-weight:700;flex-grow:1;width:250px;max-width:100%} @@ -3751,7 +3788,7 @@ typo3-backend-live-search-result-item-action>* .livesearch-result-item-title .sm .resource-tiles-container { container-type: inline-size; - margin-bottom: var(--typo3-component-spacing); + margin-bottom: var(--typo3-spacing); } @container (min-width: 480px) { @@ -3781,7 +3818,7 @@ typo3-backend-live-search-result-item-action>* .livesearch-result-item-title .sm .resource-tile-image{display:flex;height:100%;width:100%;justify-content:center;align-items:center} .resource-tile-image img{max-height:100%;max-width:100%;outline:2px solid #fff;outline-offset:0;border-radius:2px;box-shadow:0 0 4px 4px rgba(0,0,0,.05)} .resource-tile-image-icon{position:absolute;top:calc(var(--resource-tile-spacing) * -.5);left:calc(var(--resource-tile-spacing) * -.5)} -.resource-tile-nameplate{display:flex;flex-direction:column;padding:var(--resource-tile-spacing);text-align:center;font-size:var(--resource-tile-nameplate-size)} +.resource-tile-nameplate{display:flex;flex-direction:column;padding:var(--resource-tile-spacing);text-align:center;font-size:var(--resource-tile-nameplate-size);width:100%} .resource-tile-nameplate-label{overflow:hidden;white-space:nowrap;text-overflow:ellipsis} .resource-tile-nameplate-activity{font-size:var(--resource-tile-nameplate-activity-size);opacity:.75} .resource-tile-checkbox{display:none;position:absolute;font-size:var(--resource-tile-checkbox-size);right:calc(var(--resource-tile-spacing)/ 2);top:calc(var(--resource-tile-spacing)/ 2)} @@ -3790,7 +3827,7 @@ typo3-backend-live-search-result-item-action>* .livesearch-result-item-title .sm .resource-dragpreview-counter{display:flex;justify-content:center;align-items:center;height:32px;min-width:32px} .resource-dragpreview-thumbnails{display:flex;gap:2px} .resource-dragpreview-thumbnails img{height:32px;width:32px;background-color:#fff} -.recordsearchbox-container{margin-bottom:var(--typo3-component-spacing)} +.recordsearchbox-container{margin-bottom:var(--typo3-spacing)} .recordsearchbox-container [data-recordsearchbox-levels]{max-width:140px} :root{--treelist-color:#333;--treelist-comment-color:#666;--treelist-bg:#fff;--treelist-border-width:1px;--treelist-border-color:#ddd;--treelist-indentation:1rem;--treelist-indentation-spacer:.5rem;--treelist-item-spacer:2px;--treelist-item-line-height:24px;--treelist-control-size:16px} .treelist,.treelist ul{color:var(--treelist-color);background:var(--treelist-bg);padding:0;padding-left:calc(var(--treelist-indentation)/ 2);list-style:none;position:relative} @@ -3826,6 +3863,7 @@ typo3-backend-live-search-result-item-action>* .livesearch-result-item-title .sm .form-section{--treelist-bg:#fafafa} .indent{--indent-base:16px;--indent-level:0;margin-left:calc(var(--indent-base) * var(--indent-level))} .indent-inline-block{display:inline-block} +.pagination{flex-wrap:wrap;row-gap:4px} typo3-backend-editable-page-title{display:block;white-space:nowrap;text-overflow:ellipsis} typo3-backend-new-content-element-wizard{--typo3-component-color:var(--typo3-light-color);--typo3-component-secondary-color:var(--typo3-light-secondary-color);--typo3-component-bg:var(--typo3-light-bg);--typo3-component-border-color:var(--typo3-light-border-color);--typo3-component-link-color:var(--typo3-light-link-color);--typo3-component-link-hover-color:var(--typo3-light-link-hover-color);--typo3-component-hover-color:var(--typo3-light-hover-color);--typo3-component-hover-bg:var(--typo3-light-hover-bg);--typo3-component-hover-border-color:var(--typo3-light-hover-border-color);--typo3-component-focus-color:var(--typo3-light-focus-color);--typo3-component-focus-bg:var(--typo3-light-focus-bg);--typo3-component-focus-border-color:var(--typo3-light-focus-border-color);--typo3-component-active-color:var(--typo3-light-active-color);--typo3-component-active-bg:var(--typo3-light-active-bg);--typo3-component-active-border-color:var(--typo3-light-active-border-color);--typo3-component-disabled-color:var(--typo3-light-disabled-color);--typo3-component-disabled-bg:var(--typo3-light-disabled-bg);--typo3-component-disabled-border-color:var(--typo3-light-disabled-border-color)} .collapse-horizontal{height:auto;width:0;vertical-align:middle;overflow:hidden} @@ -4063,8 +4101,8 @@ span.dragIcon{display:inline-block;height:16px} .card-login{margin-bottom:0} } .card-login.card-mfa .card-heading .h2,.card-login.card-mfa .card-heading h2{margin:.75rem 0} -.input-login{height:41.2px;padding:12px 12px;font-size:12px;line-height:1.3333333;border-radius:2px} -select.input-login{height:41.2px;line-height:41.2px} +.input-login{height:43.2px;padding:12px 12px;font-size:12px;line-height:1.3333333;border-radius:2px} +select.input-login{height:43.2px;line-height:43.2px} select[multiple].input-login,textarea.input-login{height:auto} .input-login{border-color:#949494} .input-login:active,.input-login:active:focus,.input-login:active:hover,.input-login:focus,.input-login:hover{outline:1px solid #000;outline-offset:-1px} @@ -4082,11 +4120,9 @@ select[multiple].input-login,textarea.input-login{height:auto} .typo3-login-copyright-text{font-size:.95em;padding-top:1em;color:#444} .typo3-login-copyright-text>:first-child{margin-top:0} .typo3-login-copyright-text>:last-child{margin-bottom:0} -.h1,h1,typo3-backend-editable-page-title{font-family:var(--typo3-header-font-family);font-variant:normal;font-weight:400} video{background-color:#000} .nowrap{white-space:nowrap} .nowrap-disabled{white-space:normal!important} -em{font-style:italic} .section{margin-bottom:15px} .diff-r{color:red} div.diff-r{background-color:red;color:#000} @@ -4139,8 +4175,6 @@ label .icon img{pointer-events:none} .formengine-field-item>.t3js-charcounter-wrapper .t3js-charcounter-min{margin:0 2px} .form-group .panel,.form-group .panel-group{overflow:visible} .form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{color:#737373} -.form-control-icon{position:absolute;top:50%;left:15px;transform:translate(0,-50%);z-index:1;pointer-events:none} -.form-control-icon+.form-control,.form-control-icon+.form-control-clearable .form-control{padding-left:3.25em} .form-group.has-error .form-label:before{content:"";vertical-align:middle;-webkit-mask:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' xml:space='preserve' viewBox='0 0 16 16'%3e%3cg class='icon-color'%3e%3cpath d='M8 2c3.3 0 6 2.7 6 6s-2.7 6-6 6-6-2.7-6-6 2.7-6 6-6m0-1C4.1 1 1 4.1 1 8s3.1 7 7 7 7-3.1 7-7-3.1-7-7-7z'/%3e%3ccircle cx='8' cy='11' r='1'/%3e%3cpath d='M8.5 9h-1l-.445-4.45A.5.5 0 0 1 7.552 4h.896a.5.5 0 0 1 .497.55L8.5 9z'/%3e%3c/g%3e%3c/svg%3e");mask:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' xml:space='preserve' viewBox='0 0 16 16'%3e%3cg class='icon-color'%3e%3cpath d='M8 2c3.3 0 6 2.7 6 6s-2.7 6-6 6-6-2.7-6-6 2.7-6 6-6m0-1C4.1 1 1 4.1 1 8s3.1 7 7 7 7-3.1 7-7-3.1-7-7-7z'/%3e%3ccircle cx='8' cy='11' r='1'/%3e%3cpath d='M8.5 9h-1l-.445-4.45A.5.5 0 0 1 7.552 4h.896a.5.5 0 0 1 .497.55L8.5 9z'/%3e%3c/g%3e%3c/svg%3e");background-color:#c83c3c;background-size:contain;display:inline-block;border-radius:50%;width:14px;height:14px} .form-group.has-error .btn-toolbar label:before{font-family:inherit;font-size:inherit;margin-right:inherit;text-align:inherit;content:"";color:inherit;display:block} select.form-select[multiple],select.form-select[size]:not([size="1"]){min-height:156px} @@ -4148,13 +4182,14 @@ select.form-select>optgroup{margin-top:9px} select.form-select>optgroup:first-child{margin-top:0} select.form-select option{padding-top:2px;padding-bottom:2px} select.icon-select option{padding-left:22px} -.form-control-clearable{position:relative;border:0;padding:0} -.form-control-clearable input[type=search]::-webkit-search-cancel-button{display:none} -.form-control-clearable .form-control{padding-right:2.3em} -.form-control-clearable .close{border:none;background-color:transparent;position:absolute;height:16px;z-index:3;top:50%;right:.5em;transform:translate(0,-50%);opacity:.2} -.form-control-clearable .close:hover{opacity:.5} -.form-control-clearable .close .icon{vertical-align:0} -.form-control-clearable:focus{box-shadow:none;border-color:inherit} +.form-control-clearable{padding-right:2.3em} +.form-control-clearable-wrapper{position:relative;border:0;padding:0} +.form-control-clearable-wrapper input[type=search]::-webkit-search-cancel-button{display:none} +.form-control-clearable-wrapper .form-control{padding-right:2.3em} +.form-control-clearable-wrapper .close{border:none;background-color:transparent;position:absolute;height:16px;z-index:3;top:50%;right:.5em;transform:translate(0,-50%);opacity:.2} +.form-control-clearable-wrapper .close:hover{opacity:.5} +.form-control-clearable-wrapper .close .icon{vertical-align:0} +.form-control-clearable-wrapper:focus{box-shadow:none;border-color:inherit} .form-notice-capslock{position:absolute;right:25px;top:50%;margin-top:-10px;height:20px;width:20px;padding:3px;z-index:10;background-color:#fff} .form-notice-capslock>img{display:block;opacity:.5} .form-section{border:1px solid #ccc;background-color:#fafafa;padding:15px 12px 3px} @@ -4189,8 +4224,8 @@ select.icon-select option{padding-left:22px} .form-multigroup-wrap .form-multigroup-item-wizard+select.form-select[multiple],.form-multigroup-wrap .form-multigroup-item-wizard+select.form-select[size]{min-height:125px} .form-multigroup-wrap .form-wizards-wrap{width:100%} textarea.formengine-textarea{resize:none} -.input-group>.form-control-clearable{flex:1 1 auto;width:1%;min-width:0} -.form-control:not(.hidden)+.form-control-clearable{flex-grow:0;width:auto} +.input-group>.form-control-clearable-wrapper{flex:1 1 auto;width:1%;min-width:0} +.form-control:not(.hidden)+.form-control-clearable-wrapper{flex-grow:0;width:auto} .form-control.hidden+.close{display:none} .sticky-form-actions{position:sticky;top:0;z-index:2;padding:calc(1rem / 2) 1rem;background:#fff} .modal-body .sticky-form-actions{margin-left:calc(var(--bs-modal-padding) * -1);margin-right:calc(var(--bs-modal-padding) * -1);margin-bottom:var(--bs-modal-padding);padding:calc(var(--bs-modal-padding)/ 2) var(--bs-modal-padding);border-bottom:var(--bs-modal-border-width) solid var(--bs-modal-border-color)} @@ -4283,7 +4318,7 @@ td.permission-column-group{padding-left:0;width:200px;white-space:nowrap} .install-tool-modal .list-group-item.active a{color:#fff} .install-tool-modal a[data-bs-toggle=collapse]{display:block} .install-tool-modal .table .t3-languagePacks-inactive,.install-tool-modal .table .t3-languagePacks-inactive td{color:#aaa} -.install-tool-modal .t3-install-displaytwinimageimages{border:1px solid #ccc;padding:10px} +.install-tool-modal .t3-install-displaytwinimageimages{border:1px solid #ccc;border-radius:4px;padding:10px;margin-bottom:var(--typo3-spacing)} .install-tool-modal .t3-install-displaytwinimagetextarea pre{border-top:0} .install-tool-modal .bg-transparent-emulation{padding:10px;text-align:center;background:url(../Images/bg_transparent_emulation.png)} .install-tool-modal .bg-transparent-emulation img{max-width:300px} @@ -4310,7 +4345,7 @@ html{scroll-behavior:smooth} :target:before{content:"";display:block;height:80px;margin:-80px 0 0} :root{--pagemodule-grid-spacing:1rem;--pagemodule-grid-inner-spacing:1rem;--pagemodule-grid-cell-header-size:1em;--pagemodule-grid-cell-border-radius:4px;--pagemodule-grid-cell-bg:#f2f2f2;--pagemodule-grid-cell-restricted-bg:#fcf1e2;--pagemodule-grid-column-unused-bg:#fcf1e2;--pagemodule-element-spacing:1rem;--pagemodule-element-bg:#fff;--pagemodule-element-border-radius:2px;--pagemodule-element-box-shadow:0 1px 2px 1px rgba(0, 0, 0, .15);--pagemodule-element-warning-bg:#fcf1e2;--pagemodule-element-warning-border-color:#f6dab1;--pagemodule-element-hidden-bg:#f2f2f2;--pagemodule-dropzone-bg:#fcf1e2;--pagemodule-dropzone-possible-bg:#dbebdb} .t3-grid-table{border-collapse:separate;border-spacing:var(--pagemodule-grid-spacing);min-width:100%;table-layout:fixed} -.t3-grid-container{overflow:hidden;margin-bottom:var(--typo3-component-spacing)} +.t3-grid-container{overflow:hidden;margin-bottom:var(--typo3-spacing)} .t3-grid-container-inner{margin:calc(var(--pagemodule-grid-spacing) * -1)} .t3-grid-cell{border-radius:var(--pagemodule-grid-cell-border-radius);background-color:var(--pagemodule-grid-cell-bg);padding:calc(var(--pagemodule-grid-inner-spacing) - var(--pagemodule-grid-spacing)) 0} .t3-grid-cell-restricted{background-color:var(--pagemodule-grid-cell-restricted-bg)} @@ -4370,7 +4405,6 @@ html{scroll-behavior:smooth} .tx_recycler_recycler tr.collapse.show{display:table-row} .scheduler-group-dragitem{cursor:move} .scheduler-group-dragitem [editable=true],.scheduler-group-dragitem a,.scheduler-group-dragitem button{cursor:initial} -.scheduler-group-panel{overflow:unset} .task-form .form-wizards-wrap{margin-bottom:.5rem!important} @media (min-width:992px){ .task-form .form-group{width:50%} diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/form-engine.js b/typo3/sysext/backend/Resources/Public/JavaScript/form-engine.js index e852f3567cd2..d7c4b85c3b33 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/form-engine.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/form-engine.js @@ -10,4 +10,4 @@ * * The TYPO3 project - inspiring people to share! */ -import DocumentService from"@typo3/core/document-service.js";import $ from"jquery";import FormEngineValidation from"@typo3/backend/form-engine-validation.js";import Icons from"@typo3/backend/icons.js";import{default as Modal}from"@typo3/backend/modal.js";import*as MessageUtility from"@typo3/backend/utility/message-utility.js";import Severity from"@typo3/backend/severity.js";import*as BackendExceptionModule from"@typo3/backend/backend-exception.js";import InteractionRequestMap from"@typo3/backend/event/interaction-request-map.js";import Utility from"@typo3/backend/utility.js";export default(function(){function e(e,t){t?n.interactionRequestMap.resolveFor(e):n.interactionRequestMap.rejectFor(e)}const t=new Map;t.set("typo3-backend-form-update-value",(e=>{const t=document.querySelector('[name="'+CSS.escape(e.elementName)+'"]'),n=document.querySelector('[data-formengine-input-name="'+CSS.escape(e.elementName)+'"]');FormEngineValidation.updateInputField(e.elementName),null!==t&&(FormEngineValidation.markFieldAsChanged(t),FormEngineValidation.validateField(t)),null!==n&&n!==t&&FormEngineValidation.validateField(n)})),t.set("typo3-backend-form-reload",(e=>{if(!e.confirmation)return void n.saveDocument();const t=Modal.advanced({title:TYPO3.lang["FormEngine.refreshRequiredTitle"],content:TYPO3.lang["FormEngine.refreshRequiredContent"],severity:Severity.warning,staticBackdrop:!0,buttons:[{text:TYPO3.lang["button.cancel"]||"Cancel",active:!0,btnClass:"btn-default",name:"cancel"},{text:TYPO3.lang["button.ok"]||"OK",btnClass:"btn-"+Severity.getCssClass(Severity.warning),name:"ok",trigger:()=>{n.saveDocument()}}]});t.addEventListener("button.clicked",(()=>t.hideModal()))})),t.set("typo3-backend-form-update-bitmask",((e,t)=>{const n=t.target,a=document.editform[e.elementName],o=n.checked!==e.invert,i=Math.pow(2,e.position),r=Math.pow(2,e.total)-i-1;a.value=o?a.value|i:a.value&r,a.dispatchEvent(new Event("change",{bubbles:!0,cancelable:!0}))}));const n={consumeTypes:["typo3.setUrl","typo3.beforeSetUrl","typo3.refresh"],Validation:FormEngineValidation,interactionRequestMap:InteractionRequestMap,formName:TYPO3.settings.FormEngine.formName,openedPopupWindow:null,legacyFieldChangedCb:function(){!$.isFunction(TYPO3.settings.FormEngine.legacyFieldChangedCb)||TYPO3.settings.FormEngine.legacyFieldChangedCb()},browserUrl:"",openPopupWindow:function(e,t,a){return Modal.advanced({type:Modal.types.iframe,content:n.browserUrl+"&mode="+e+"&bparams="+t+(a?"&"+("db"===e?"expandPage":"expandFolder")+"="+a:""),size:Modal.sizes.large})},setSelectOptionFromExternalSource:function(e,t,a,o,i,r){i=String(i);let c,l,s=!1,d=!1;l=n.getFieldElement(e),c=l.get(0);const u=l.get(0);if(null===u||"--div--"===t||u instanceof HTMLOptGroupElement)return;const m=n.getFieldElement(e,"_list",!0);if(m.length>0&&(l=m,c=l.get(0),s=l.prop("multiple")&&"1"!=l.prop("size"),d=!0),s||d){const d=n.getFieldElement(e,"_avail");if(!s){for(const e of c.querySelectorAll("option")){const t=d.find('option[value="'+$.escapeSelector($(e).attr("value"))+'"]');t.length&&(t.removeClass("hidden").prop("disabled",!1),n.enableOptGroup(t.get(0)))}l.empty()}if(i){let e=!1,a=new RegExp("(^|,)"+t+"($|,)");i.match(a)?(l.empty(),e=!0):1==l.find("option").length&&(a=new RegExp("(^|,)"+l.find("option").prop("value")+"($|,)"),i.match(a)&&(l.empty(),e=!0)),e&&void 0!==r&&r.closest("select").querySelectorAll("[disabled]").forEach((function(e){e.classList.remove("hidden"),e.disabled=!1,n.enableOptGroup(e)}))}let m=!0;const f=n.getFieldElement(e,"_mul",!0);if(0==f.length||0==f.val()){for(const e of c.querySelectorAll("option"))if(e.value==t){m=!1;break}if(m&&void 0!==r){r.classList.add("hidden"),r.disabled=!0;const e=r.parentElement;e instanceof HTMLOptGroupElement&&0===e.querySelectorAll("option:not([disabled]):not([hidden]):not(.hidden)").length&&(e.disabled=!0,e.classList.add("hidden"))}}if(m){const e=$("<option></option>");e.attr({value:t,title:o}).text(a),e.appendTo(l),n.updateHiddenFieldValueFromSelect(c,u),n.legacyFieldChangedCb(),FormEngineValidation.markFieldAsChanged(u),n.Validation.validateField(l),n.Validation.validateField(d)}}else{const e=/_(\d+)$/,a=t.toString().match(e);null!=a&&(t=a[1]),l.val(t),n.Validation.validateField(l)}},updateHiddenFieldValueFromSelect:function(e,t){const n=Array.from(e.options).map((e=>e.value));t.value=n.join(","),t.dispatchEvent(new Event("change",{bubbles:!0,cancelable:!0}))},getFormElement:function(e){const t=$('form[name="'+n.formName+'"]:first');if(!e)return t;{const a=n.getFieldElement(e),o=n.getFieldElement(e,"_list");if(a.length>0&&("select-one"===a.prop("type")||o.length>0&&o.prop("type").match(/select-(one|multiple)/)))return t;console.error("Form fields missing: form: "+n.formName+", field name: "+e),alert("Form field is invalid")}},getFieldElement:function(e,t,a){const o=$('form[name="'+n.formName+'"]:first');if(t){let n;switch(t){case"_list":n=$(':input[data-formengine-input-name="'+e+'"]:not([type=hidden])',o);break;case"_avail":n=$(':input[data-relatedfieldname="'+e+'"]',o);break;case"_mul":case"_hr":n=$(':input[type=hidden][data-formengine-input-name="'+e+'"]',o);break;default:n=null}if(n&&n.length>0||!0===a)return n}return $(':input[name="'+e+'"]',o)},initializeEvents:function(){top.TYPO3&&void 0!==top.TYPO3.Backend&&(top.TYPO3.Backend.consumerScope.attach(n),$(window).on("unload",(function(){top.TYPO3.Backend.consumerScope.detach(n)}))),$(document).on("click",".t3js-editform-close",(e=>{e.preventDefault(),n.preventExitIfNotSaved(n.preventExitIfNotSavedCallback)})).on("click",".t3js-editform-view",(e=>{e.preventDefault(),n.previewAction(e,n.previewActionCallback)})).on("click",".t3js-editform-new",(e=>{e.preventDefault(),n.newAction(e,n.newActionCallback)})).on("click",".t3js-editform-duplicate",(e=>{e.preventDefault(),n.duplicateAction(e,n.duplicateActionCallback)})).on("click",".t3js-editform-delete-record",(e=>{e.preventDefault(),n.deleteAction(e,n.deleteActionCallback)})).on("click",".t3js-editform-submitButton",(e=>{const t=$(e.currentTarget),n=t.data("name")||e.currentTarget.name,a=$("<input />").attr("type","hidden").attr("name",n).attr("value","1");t.parents("form").append(a)})).on("change",'.t3-form-field-eval-null-checkbox input[type="checkbox"]',(e=>{$(e.currentTarget).closest(".t3js-formengine-field-item").toggleClass("disabled")})).on("change",'.t3js-form-field-eval-null-placeholder-checkbox input[type="checkbox"]',(e=>{n.toggleCheckboxField($(e.currentTarget)),FormEngineValidation.markFieldAsChanged($(e.currentTarget))})).on("change",(()=>{$(".module-docheader-bar .btn").removeClass("disabled").prop("disabled",!1)})).on("click",".t3js-element-browser",(function(e){e.preventDefault(),e.stopPropagation();const t=$(e.currentTarget),a=t.data("mode"),o=t.data("params"),i=t.data("entryPoint");n.openPopupWindow(a,o,i)})).on("click",'[data-formengine-field-change-event="click"]',(e=>{const t=JSON.parse(e.currentTarget.dataset.formengineFieldChangeItems);n.processOnFieldChange(t,e)})).on("change",'[data-formengine-field-change-event="change"]',(e=>{const t=JSON.parse(e.currentTarget.dataset.formengineFieldChangeItems);n.processOnFieldChange(t,e)})),document.editform.addEventListener("submit",(function(){if(document.editform.closeDoc.value)return;const e=["button[form]",'button[name^="_save"]','a[data-name^="_save"]','button[name="CMD"][value^="save"]','a[data-name="CMD"][data-value^="save"]'].join(","),t=document.querySelector(e);null!==t&&(t.disabled=!0,Icons.getIcon("spinner-circle-dark",Icons.sizes.small).then((function(e){t.querySelector(".t3js-icon").outerHTML=e})))})),window.addEventListener("message",n.handlePostMessage)},consume:function(t){if(!t)throw new BackendExceptionModule.BackendException("No interaction request given",1496589980);const a=$.Deferred();if(t.concernsTypes(n.consumeTypes)){const o=t.outerMostRequest;n.interactionRequestMap.attachFor(o,a),o.isProcessed()?e(o,o.getProcessedData().response):n.hasChange()?n.preventExitIfNotSaved((function(t){o.setProcessedData({response:t}),e(o,t)})):n.interactionRequestMap.resolveFor(o)}return a},handlePostMessage:function(e){if(!MessageUtility.MessageUtility.verifyOrigin(e.origin))throw"Denied message sent by "+e.origin;if("typo3:elementBrowser:elementAdded"===e.data.actionName){if(void 0===e.data.fieldName)throw"fieldName not defined in message";if(void 0===e.data.value)throw"value not defined in message";const t=e.data.label||e.data.value,a=e.data.title||t,o=e.data.exclusiveValues||"";n.setSelectOptionFromExternalSource(e.data.fieldName,e.data.value,t,a,o)}},initializeRemainingCharacterViews:function(){const e=$("[maxlength]").not(".t3js-datetimepicker").not(".t3js-color-picker").not(".t3js-charcounter-initialized");e.on("focus",(e=>{const t=$(e.currentTarget),a=t.parents(".t3js-formengine-field-item:first"),o=n.getCharacterCounterProperties(t);let i=a.find(".t3js-charcounter-wrapper");i.length||(i=$("<div>"),i.addClass("t3js-charcounter-wrapper"),a.append(i)),i.append($("<div />",{class:"t3js-charcounter"}).append($("<span />",{class:o.labelClass}).text(TYPO3.lang["FormEngine.remainingCharacters"].replace("{0}",o.remainingCharacters))))})).on("blur",(e=>{$(e.currentTarget).parents(".t3js-formengine-field-item:first").find(".t3js-charcounter").remove()})).on("keyup",(e=>{const t=$(e.currentTarget),a=t.parents(".t3js-formengine-field-item:first"),o=n.getCharacterCounterProperties(t);a.find(".t3js-charcounter span").removeClass().addClass(o.labelClass).text(TYPO3.lang["FormEngine.remainingCharacters"].replace("{0}",o.remainingCharacters))})),e.addClass("t3js-charcounter-initialized")},getCharacterCounterProperties:function(e){const t=e.val(),n=parseInt(e.attr("maxlength"),10)-t.length-(t.match(/\n/g)||[]).length;let a="";return a=n<15?"badge-danger":n<30?"badge-warning":"badge-info",{remainingCharacters:n,labelClass:"badge "+a}},initializeMinimumCharactersLeftViews:function(){const e=(e,t)=>{const n=t.currentTarget.closest(".t3js-formengine-field-item"),a=n.querySelector(".t3js-charcounter-min"),o=TYPO3.lang["FormEngine.minCharactersLeft"].replace("{0}",e);if(a)a.querySelector("span").innerHTML=o;else{const e=document.createElement("div");e.classList.add("t3js-charcounter-min");const t=document.createElement("span");t.classList.add("badge","badge-danger"),t.innerHTML=o,e.append(t);let a=n.querySelector(".t3js-charcounter-wrapper");a||(a=document.createElement("div"),a.classList.add("t3js-charcounter-wrapper"),n.append(a)),a.prepend(e)}},t=e=>{const t=e.currentTarget.closest(".t3js-formengine-field-item").querySelector(".t3js-charcounter-min");t&&t.remove()};document.querySelectorAll("[minlength]:not(.t3js-datetimepicker):not(.t3js-charcounter-min-initialized)").forEach((a=>{a.addEventListener("focus",(t=>{const o=n.getMinCharacterLeftCount(a);o>0&&e(o,t)})),a.addEventListener("blur",t),a.addEventListener("keyup",(o=>{const i=n.getMinCharacterLeftCount(a);i>0?e(i,o):t(o)}))}))},getMinCharacterLeftCount:function(e){const t=e.value,n=e.minLength,a=t.length;if(0===a)return 0;return n-a-(t.match(/\n/g)||[]).length},initializeNullNoPlaceholderCheckboxes:function(){document.querySelectorAll(".t3-form-field-eval-null-checkbox").forEach((e=>{const t=e.querySelector('input[type="checkbox"]'),n=e.closest(".t3js-formengine-field-item");t.checked||n.classList.add("disabled")}))},initializeNullWithPlaceholderCheckboxes:function(){document.querySelectorAll(".t3js-form-field-eval-null-placeholder-checkbox").forEach((e=>{n.toggleCheckboxField($(e).find('input[type="checkbox"]'),!1)}))},toggleCheckboxField:function(e,t=!0){const n=e.closest(".t3js-formengine-field-item");e.prop("checked")?(n.find(".t3js-formengine-placeholder-placeholder").hide(),n.find(".t3js-formengine-placeholder-formfield").show(),t&&n.find(".t3js-formengine-placeholder-formfield").find(":input").trigger("focus")):(n.find(".t3js-formengine-placeholder-placeholder").show(),n.find(".t3js-formengine-placeholder-formfield").hide())},reinitialize:function(){const e=Array.from(document.querySelectorAll(".t3js-clearable"));e.length>0&&import("@typo3/backend/input/clearable.js").then((function(){e.forEach((e=>e.clearable()))})),n.initializeNullNoPlaceholderCheckboxes(),n.initializeNullWithPlaceholderCheckboxes(),n.initializeLocalizationStateSelector(),n.initializeMinimumCharactersLeftViews(),n.initializeRemainingCharacterViews()},initializeLocalizationStateSelector:function(){document.querySelectorAll(".t3js-l10n-state-container").forEach((e=>{const t=e.closest(".t3js-formengine-field-item")?.querySelector("[data-formengine-input-name]");if(void 0===t)return;const n=e.querySelector('input[type="radio"]:checked').value;"parent"!==n&&"source"!==n||(t.disabled=!0)}))},hasChange:function(){const e=$('form[name="'+n.formName+'"] .has-change').length>0,t=$('[name^="data["].has-change').length>0;return e||t},preventExitIfNotSavedCallback:()=>{n.closeDocument()},preventFollowLinkIfNotSaved:function(e){return n.preventExitIfNotSaved((function(){window.location.href=e})),!1},preventExitIfNotSaved:function(e){if(e=e||n.preventExitIfNotSavedCallback,n.hasChange()){const t=TYPO3.lang["label.confirm.close_without_save.title"]||"Do you want to close without saving?",a=TYPO3.lang["label.confirm.close_without_save.content"]||"You currently have unsaved changes. Are you sure you want to discard these changes?",o=$("<input />").attr("type","hidden").attr("name","_saveandclosedok").attr("value","1"),i=[{text:TYPO3.lang["buttons.confirm.close_without_save.no"]||"No, I will continue editing",btnClass:"btn-default",name:"no"},{text:TYPO3.lang["buttons.confirm.close_without_save.yes"]||"Yes, discard my changes",btnClass:"btn-default",name:"yes"}];0===$(".has-error").length&&i.push({text:TYPO3.lang["buttons.confirm.save_and_close"]||"Save and close",btnClass:"btn-primary",name:"save",active:!0});const r=Modal.confirm(t,a,Severity.warning,i);r.addEventListener("button.clicked",(function(t){"no"===t.target.name?r.hideModal():"yes"===t.target.name?(r.hideModal(),e.call(null,!0)):"save"===t.target.name&&($("form[name="+n.formName+"]").append(o),r.hideModal(),n.saveDocument())}))}else e.call(null,!0)},preventSaveIfHasErrors:function(){if($(".has-error").length>0){const e=TYPO3.lang["label.alert.save_with_error.title"]||"You have errors in your form!",t=TYPO3.lang["label.alert.save_with_error.content"]||"Please check the form, there is at least one error in your form.",n=Modal.confirm(e,t,Severity.error,[{text:TYPO3.lang["buttons.alert.save_with_error.ok"]||"OK",btnClass:"btn-danger",name:"ok"}]);return n.addEventListener("button.clicked",(function(e){"ok"===e.target.name&&n.hideModal()})),!1}return!0},requestFormEngineUpdate:function(e){if(e){const e=Modal.advanced({title:TYPO3.lang["FormEngine.refreshRequiredTitle"],content:TYPO3.lang["FormEngine.refreshRequiredContent"],severity:Severity.warning,staticBackdrop:!0,buttons:[{text:TYPO3.lang["button.cancel"]||"Cancel",active:!0,btnClass:"btn-default",name:"cancel",trigger:()=>{e.hideModal()}},{text:TYPO3.lang["button.ok"]||"OK",btnClass:"btn-"+Severity.getCssClass(Severity.warning),name:"ok",trigger:()=>{n.closeModalsRecursive(),n.saveDocument()}}]})}else n.saveDocument()},processOnFieldChange:function(e,n){e.forEach((e=>{const a=t.get(e.name);a instanceof Function&&a.call(null,e.data||null,n)}))},registerOnFieldChangeHandler:function(e,n){t.has(e)&&console.warn("Handler for onFieldChange name `"+e+"` has been overridden."),t.set(e,n)},closeModalsRecursive:function(){void 0!==Modal.currentModal&&null!==Modal.currentModal&&(Modal.currentModal.addEventListener("typo3-modal-hidden",(function(){n.closeModalsRecursive()})),Modal.currentModal.hideModal())},previewAction:function(e,t){t=t||n.previewActionCallback;const a=e.currentTarget.href,o="isNew"in e.target.dataset,i=$("<input />").attr("type","hidden").attr("name","_savedokview").attr("value","1");n.hasChange()?n.showPreviewModal(a,o,i,t):($("form[name="+n.formName+"]").append(i),window.open("","newTYPO3frontendWindow"),document.editform.submit())},previewActionCallback:function(e,t,a){switch(Modal.dismiss(),e){case"discard":const e=window.open(t,"newTYPO3frontendWindow");e.focus(),Utility.urlsPointToSameServerSideResource(e.location.href,t)&&e.location.reload();break;case"save":$("form[name="+n.formName+"]").append($(a)),window.open("","newTYPO3frontendWindow"),n.saveDocument()}},showPreviewModal:function(e,t,n,a){const o=TYPO3.lang["label.confirm.view_record_changed.title"]||"Do you want to save before viewing?",i={text:TYPO3.lang["buttons.confirm.view_record_changed.cancel"]||"Cancel",btnClass:"btn-default",name:"cancel"},r={text:TYPO3.lang["buttons.confirm.view_record_changed.no-save"]||"View without changes",btnClass:"btn-default",name:"discard"},c={text:TYPO3.lang["buttons.confirm.view_record_changed.save"]||"Save changes and view",btnClass:"btn-primary",name:"save",active:!0};let l=[],s="";t?(l=[i,c],s=TYPO3.lang["label.confirm.view_record_changed.content.is-new-page"]||"You need to save your changes before viewing the page. Do you want to save and view them now?"):(l=[i,r,c],s=TYPO3.lang["label.confirm.view_record_changed.content"]||"You currently have unsaved changes. You can either discard these changes or save and view them.");const d=Modal.confirm(o,s,Severity.info,l);d.addEventListener("button.clicked",(function(t){a(t.target.name,e,n,d)}))},newAction:function(e,t){t=t||n.newActionCallback;const a=$("<input />").attr("type","hidden").attr("name","_savedoknew").attr("value","1"),o="isNew"in e.target.dataset;n.hasChange()?n.showNewModal(o,a,t):($("form[name="+n.formName+"]").append(a),document.editform.submit())},newActionCallback:function(e,t){const a=$("form[name="+n.formName+"]");switch(Modal.dismiss(),e){case"no":a.append(t),document.editform.submit();break;case"yes":a.append(t),n.saveDocument()}},showNewModal:function(e,t,n){const a=TYPO3.lang["label.confirm.new_record_changed.title"]||"Do you want to save before adding?",o=TYPO3.lang["label.confirm.new_record_changed.content"]||"You need to save your changes before creating a new record. Do you want to save and create now?";let i=[];const r={text:TYPO3.lang["buttons.confirm.new_record_changed.cancel"]||"Cancel",btnClass:"btn-default",name:"cancel"},c={text:TYPO3.lang["buttons.confirm.new_record_changed.no"]||"No, just add",btnClass:"btn-default",name:"no"},l={text:TYPO3.lang["buttons.confirm.new_record_changed.yes"]||"Yes, save and create now",btnClass:"btn-primary",name:"yes",active:!0};i=e?[r,l]:[r,c,l];Modal.confirm(a,o,Severity.info,i).addEventListener("button.clicked",(function(e){n(e.target.name,t)}))},duplicateAction:function(e,t){t=t||n.duplicateActionCallback;const a=$("<input />").attr("type","hidden").attr("name","_duplicatedoc").attr("value","1"),o="isNew"in e.target.dataset;n.hasChange()?n.showDuplicateModal(o,a,t):($("form[name="+n.formName+"]").append(a),document.editform.submit())},duplicateActionCallback:function(e,t){const a=$("form[name="+n.formName+"]");switch(Modal.dismiss(),e){case"no":a.append(t),document.editform.submit();break;case"yes":a.append(t),n.saveDocument()}},showDuplicateModal:function(e,t,n){const a=TYPO3.lang["label.confirm.duplicate_record_changed.title"]||"Do you want to save before duplicating this record?",o=TYPO3.lang["label.confirm.duplicate_record_changed.content"]||"You currently have unsaved changes. Do you want to save your changes before duplicating this record?";let i=[];const r={text:TYPO3.lang["buttons.confirm.duplicate_record_changed.cancel"]||"Cancel",btnClass:"btn-default",name:"cancel"},c={text:TYPO3.lang["buttons.confirm.duplicate_record_changed.no"]||"No, just duplicate the original",btnClass:"btn-default",name:"no"},l={text:TYPO3.lang["buttons.confirm.duplicate_record_changed.yes"]||"Yes, save and duplicate this record",btnClass:"btn-primary",name:"yes",active:!0};i=e?[r,l]:[r,c,l];Modal.confirm(a,o,Severity.info,i).addEventListener("button.clicked",(function(e){n(e.target.name,t)}))},deleteAction:function(e,t){t=t||n.deleteActionCallback;const a=$(e.target);n.showDeleteModal(a,t)},deleteActionCallback:function(e,t){Modal.dismiss(),"yes"===e&&n.invokeRecordDeletion(t)},showDeleteModal:function(e,t){const n=TYPO3.lang["label.confirm.delete_record.title"]||"Delete this record?";let a=(TYPO3.lang["label.confirm.delete_record.content"]||"Are you sure you want to delete the record '%s'?").replace("%s",e.data("record-info"));e.data("reference-count-message")&&(a+="\n"+e.data("reference-count-message")),e.data("translation-count-message")&&(a+="\n"+e.data("translation-count-message"));Modal.confirm(n,a,Severity.warning,[{text:TYPO3.lang["buttons.confirm.delete_record.no"]||"Cancel",btnClass:"btn-default",name:"no"},{text:TYPO3.lang["buttons.confirm.delete_record.yes"]||"Yes, delete this record",btnClass:"btn-warning",name:"yes",active:!0}]).addEventListener("button.clicked",(function(n){t(n.target.name,e)}))},enableOptGroup:function(e){const t=e.parentElement;t instanceof HTMLOptGroupElement&&t.querySelectorAll("option:not([hidden]):not([disabled]):not(.hidden)").length&&(t.hidden=!1,t.disabled=!1,t.classList.remove("hidden"))},closeDocument:function(){document.editform.closeDoc.value=1,n.dispatchSubmitEvent(),document.editform.submit()},saveDocument:function(){document.editform.doSave.value=1,n.dispatchSubmitEvent(),document.editform.submit()},dispatchSubmitEvent:function(){const e=document.createEvent("Event");e.initEvent("submit",!1,!0),document.editform.dispatchEvent(e)},initialize:function(e){n.browserUrl=e,DocumentService.ready().then((()=>{n.initializeEvents(),n.Validation.initialize(),n.reinitialize(),$("#t3js-ui-block").remove()}))},invokeRecordDeletion:function(e){window.location.href=e.attr("href")}};if(void 0!==TYPO3.settings.RequireJS&&void 0!==TYPO3.settings.RequireJS.PostInitializationModules["TYPO3/CMS/Backend/FormEngine"])for(const e of TYPO3.settings.RequireJS.PostInitializationModules["TYPO3/CMS/Backend/FormEngine"])window.require([e]);return TYPO3.FormEngine=n,n}()); \ No newline at end of file +import DocumentService from"@typo3/core/document-service.js";import $ from"jquery";import FormEngineValidation from"@typo3/backend/form-engine-validation.js";import Icons from"@typo3/backend/icons.js";import{default as Modal}from"@typo3/backend/modal.js";import*as MessageUtility from"@typo3/backend/utility/message-utility.js";import Severity from"@typo3/backend/severity.js";import*as BackendExceptionModule from"@typo3/backend/backend-exception.js";import InteractionRequestMap from"@typo3/backend/event/interaction-request-map.js";import Utility from"@typo3/backend/utility.js";export default(function(){function e(e,t){t?n.interactionRequestMap.resolveFor(e):n.interactionRequestMap.rejectFor(e)}const t=new Map;t.set("typo3-backend-form-update-value",(e=>{const t=document.querySelector('[name="'+CSS.escape(e.elementName)+'"]'),n=document.querySelector('[data-formengine-input-name="'+CSS.escape(e.elementName)+'"]');FormEngineValidation.updateInputField(e.elementName),null!==t&&(FormEngineValidation.markFieldAsChanged(t),FormEngineValidation.validateField(t)),null!==n&&n!==t&&FormEngineValidation.validateField(n)})),t.set("typo3-backend-form-reload",(e=>{if(!e.confirmation)return void n.saveDocument();const t=Modal.advanced({title:TYPO3.lang["FormEngine.refreshRequiredTitle"],content:TYPO3.lang["FormEngine.refreshRequiredContent"],severity:Severity.warning,staticBackdrop:!0,buttons:[{text:TYPO3.lang["button.cancel"]||"Cancel",active:!0,btnClass:"btn-default",name:"cancel"},{text:TYPO3.lang["button.ok"]||"OK",btnClass:"btn-"+Severity.getCssClass(Severity.warning),name:"ok",trigger:()=>{n.saveDocument()}}]});t.addEventListener("button.clicked",(()=>t.hideModal()))})),t.set("typo3-backend-form-update-bitmask",((e,t)=>{const n=t.target,a=document.editform[e.elementName],o=n.checked!==e.invert,i=Math.pow(2,e.position),r=Math.pow(2,e.total)-i-1;a.value=o?a.value|i:a.value&r,a.dispatchEvent(new Event("change",{bubbles:!0,cancelable:!0}))}));const n={consumeTypes:["typo3.setUrl","typo3.beforeSetUrl","typo3.refresh"],Validation:FormEngineValidation,interactionRequestMap:InteractionRequestMap,formName:TYPO3.settings.FormEngine.formName,openedPopupWindow:null,legacyFieldChangedCb:function(){!$.isFunction(TYPO3.settings.FormEngine.legacyFieldChangedCb)||TYPO3.settings.FormEngine.legacyFieldChangedCb()},browserUrl:"",openPopupWindow:function(e,t,a){return Modal.advanced({type:Modal.types.iframe,content:n.browserUrl+"&mode="+e+"&bparams="+t+(a?"&"+("db"===e?"expandPage":"expandFolder")+"="+a:""),size:Modal.sizes.large})},setSelectOptionFromExternalSource:function(e,t,a,o,i,r){i=String(i);let c,l,s=!1,d=!1;l=n.getFieldElement(e),c=l.get(0);const u=l.get(0);if(null===u||"--div--"===t||u instanceof HTMLOptGroupElement)return;const m=n.getFieldElement(e,"_list",!0);if(m.length>0&&(l=m,c=l.get(0),s=l.prop("multiple")&&"1"!=l.prop("size"),d=!0),s||d){const d=n.getFieldElement(e,"_avail");if(!s){for(const e of c.querySelectorAll("option")){const t=d.find('option[value="'+$.escapeSelector($(e).attr("value"))+'"]');t.length&&(t.removeClass("hidden").prop("disabled",!1),n.enableOptGroup(t.get(0)))}l.empty()}if(i){let e=!1,a=new RegExp("(^|,)"+t+"($|,)");i.match(a)?(l.empty(),e=!0):1==l.find("option").length&&(a=new RegExp("(^|,)"+l.find("option").prop("value")+"($|,)"),i.match(a)&&(l.empty(),e=!0)),e&&void 0!==r&&r.closest("select").querySelectorAll("[disabled]").forEach((function(e){e.classList.remove("hidden"),e.disabled=!1,n.enableOptGroup(e)}))}let m=!0;const f=n.getFieldElement(e,"_mul",!0);if(0==f.length||0==f.val()){for(const e of c.querySelectorAll("option"))if(e.value==t){m=!1;break}if(m&&void 0!==r){r.classList.add("hidden"),r.disabled=!0;const e=r.parentElement;e instanceof HTMLOptGroupElement&&0===e.querySelectorAll("option:not([disabled]):not([hidden]):not(.hidden)").length&&(e.disabled=!0,e.classList.add("hidden"))}}if(m){const e=$("<option></option>");e.attr({value:t,title:o}).text(a),e.appendTo(l),n.updateHiddenFieldValueFromSelect(c,u),n.legacyFieldChangedCb(),FormEngineValidation.markFieldAsChanged(u),n.Validation.validateField(l),n.Validation.validateField(d)}}else{const e=/_(\d+)$/,a=t.toString().match(e);null!=a&&(t=a[1]),l.val(t),n.Validation.validateField(l)}},updateHiddenFieldValueFromSelect:function(e,t){const n=Array.from(e.options).map((e=>e.value));t.value=n.join(","),t.dispatchEvent(new Event("change",{bubbles:!0,cancelable:!0}))},getFormElement:function(e){const t=$('form[name="'+n.formName+'"]:first');if(!e)return t;{const a=n.getFieldElement(e),o=n.getFieldElement(e,"_list");if(a.length>0&&("select-one"===a.prop("type")||o.length>0&&o.prop("type").match(/select-(one|multiple)/)))return t;console.error("Form fields missing: form: "+n.formName+", field name: "+e),alert("Form field is invalid")}},getFieldElement:function(e,t,a){const o=$('form[name="'+n.formName+'"]:first');if(t){let n;switch(t){case"_list":n=$(':input[data-formengine-input-name="'+e+'"]:not([type=hidden])',o);break;case"_avail":n=$(':input[data-relatedfieldname="'+e+'"]',o);break;case"_mul":case"_hr":n=$(':input[type=hidden][data-formengine-input-name="'+e+'"]',o);break;default:n=null}if(n&&n.length>0||!0===a)return n}return $(':input[name="'+e+'"]',o)},initializeEvents:function(){top.TYPO3&&void 0!==top.TYPO3.Backend&&(top.TYPO3.Backend.consumerScope.attach(n),$(window).on("unload",(function(){top.TYPO3.Backend.consumerScope.detach(n)}))),$(document).on("click",".t3js-editform-close",(e=>{e.preventDefault(),n.preventExitIfNotSaved(n.preventExitIfNotSavedCallback)})).on("click",".t3js-editform-view",(e=>{e.preventDefault(),n.previewAction(e,n.previewActionCallback)})).on("click",".t3js-editform-new",(e=>{e.preventDefault(),n.newAction(e,n.newActionCallback)})).on("click",".t3js-editform-duplicate",(e=>{e.preventDefault(),n.duplicateAction(e,n.duplicateActionCallback)})).on("click",".t3js-editform-delete-record",(e=>{e.preventDefault(),n.deleteAction(e,n.deleteActionCallback)})).on("click",".t3js-editform-submitButton",(e=>{const t=$(e.currentTarget),n=t.data("name")||e.currentTarget.name,a=$("<input />").attr("type","hidden").attr("name",n).attr("value","1");t.parents("form").append(a)})).on("change",'.t3-form-field-eval-null-checkbox input[type="checkbox"]',(e=>{$(e.currentTarget).closest(".t3js-formengine-field-item").toggleClass("disabled")})).on("change",'.t3js-form-field-eval-null-placeholder-checkbox input[type="checkbox"]',(e=>{n.toggleCheckboxField($(e.currentTarget)),FormEngineValidation.markFieldAsChanged($(e.currentTarget))})).on("change",(()=>{$(".module-docheader-bar .btn").removeClass("disabled").prop("disabled",!1)})).on("click",".t3js-element-browser",(function(e){e.preventDefault(),e.stopPropagation();const t=$(e.currentTarget),a=t.data("mode"),o=t.data("params"),i=t.data("entryPoint");n.openPopupWindow(a,o,i)})).on("click",'[data-formengine-field-change-event="click"]',(e=>{const t=JSON.parse(e.currentTarget.dataset.formengineFieldChangeItems);n.processOnFieldChange(t,e)})).on("change",'[data-formengine-field-change-event="change"]',(e=>{const t=JSON.parse(e.currentTarget.dataset.formengineFieldChangeItems);n.processOnFieldChange(t,e)})),document.editform.addEventListener("submit",(function(){if(document.editform.closeDoc.value)return;const e=["button[form]",'button[name^="_save"]','a[data-name^="_save"]','button[name="CMD"][value^="save"]','a[data-name="CMD"][data-value^="save"]'].join(","),t=document.querySelector(e);null!==t&&(t.disabled=!0,Icons.getIcon("spinner-circle-dark",Icons.sizes.small).then((function(e){t.querySelector(".t3js-icon").outerHTML=e})))})),window.addEventListener("message",n.handlePostMessage)},consume:function(t){if(!t)throw new BackendExceptionModule.BackendException("No interaction request given",1496589980);const a=$.Deferred();if(t.concernsTypes(n.consumeTypes)){const o=t.outerMostRequest;n.interactionRequestMap.attachFor(o,a),o.isProcessed()?e(o,o.getProcessedData().response):n.hasChange()?n.preventExitIfNotSaved((function(t){o.setProcessedData({response:t}),e(o,t)})):n.interactionRequestMap.resolveFor(o)}return a},handlePostMessage:function(e){if(!MessageUtility.MessageUtility.verifyOrigin(e.origin))throw"Denied message sent by "+e.origin;if("typo3:elementBrowser:elementAdded"===e.data.actionName){if(void 0===e.data.fieldName)throw"fieldName not defined in message";if(void 0===e.data.value)throw"value not defined in message";const t=e.data.label||e.data.value,a=e.data.title||t,o=e.data.exclusiveValues||"";n.setSelectOptionFromExternalSource(e.data.fieldName,e.data.value,t,a,o)}},initializeRemainingCharacterViews:function(){const e=$("[maxlength]").not(".t3js-datetimepicker").not(".t3js-color-picker").not(".t3js-charcounter-initialized");e.on("focus",(e=>{const t=$(e.currentTarget),a=t.parents(".t3js-formengine-field-item:first"),o=n.getCharacterCounterProperties(t);let i=a.find(".t3js-charcounter-wrapper");i.length||(i=$("<div>"),i.addClass("t3js-charcounter-wrapper"),a.append(i)),i.append($("<div />",{class:"t3js-charcounter"}).append($("<span />",{class:o.labelClass}).text(TYPO3.lang["FormEngine.remainingCharacters"].replace("{0}",o.remainingCharacters))))})).on("blur",(e=>{$(e.currentTarget).parents(".t3js-formengine-field-item:first").find(".t3js-charcounter").remove()})).on("keyup",(e=>{const t=$(e.currentTarget),a=t.parents(".t3js-formengine-field-item:first"),o=n.getCharacterCounterProperties(t);a.find(".t3js-charcounter span").removeClass().addClass(o.labelClass).text(TYPO3.lang["FormEngine.remainingCharacters"].replace("{0}",o.remainingCharacters))})),e.addClass("t3js-charcounter-initialized")},getCharacterCounterProperties:function(e){const t=e.val(),n=parseInt(e.attr("maxlength"),10)-t.length-(t.match(/\n/g)||[]).length;let a="";return a=n<15?"badge-danger":n<30?"badge-warning":"badge-info",{remainingCharacters:n,labelClass:"badge "+a}},initializeMinimumCharactersLeftViews:function(){const e=(e,t)=>{const n=t.currentTarget.closest(".t3js-formengine-field-item"),a=n.querySelector(".t3js-charcounter-min"),o=TYPO3.lang["FormEngine.minCharactersLeft"].replace("{0}",e);if(a)a.querySelector("span").innerHTML=o;else{const e=document.createElement("div");e.classList.add("t3js-charcounter-min");const t=document.createElement("span");t.classList.add("badge","badge-danger"),t.innerHTML=o,e.append(t);let a=n.querySelector(".t3js-charcounter-wrapper");a||(a=document.createElement("div"),a.classList.add("t3js-charcounter-wrapper"),n.append(a)),a.prepend(e)}},t=e=>{const t=e.currentTarget.closest(".t3js-formengine-field-item").querySelector(".t3js-charcounter-min");t&&t.remove()};document.querySelectorAll("[minlength]:not(.t3js-datetimepicker):not(.t3js-charcounter-min-initialized)").forEach((a=>{a.addEventListener("focus",(t=>{const o=n.getMinCharacterLeftCount(a);o>0&&e(o,t)})),a.addEventListener("blur",t),a.addEventListener("keyup",(o=>{const i=n.getMinCharacterLeftCount(a);i>0?e(i,o):t(o)}))}))},getMinCharacterLeftCount:function(e){const t=e.value,n=e.minLength,a=t.length;if(0===a)return 0;return n-a-(t.match(/\n/g)||[]).length},initializeNullNoPlaceholderCheckboxes:function(){document.querySelectorAll(".t3-form-field-eval-null-checkbox").forEach((e=>{const t=e.querySelector('input[type="checkbox"]'),n=e.closest(".t3js-formengine-field-item");t.checked||n.classList.add("disabled")}))},initializeNullWithPlaceholderCheckboxes:function(){document.querySelectorAll(".t3js-form-field-eval-null-placeholder-checkbox").forEach((e=>{n.toggleCheckboxField($(e).find('input[type="checkbox"]'),!1)}))},toggleCheckboxField:function(e,t=!0){const n=e.closest(".t3js-formengine-field-item");e.prop("checked")?(n.find(".t3js-formengine-placeholder-placeholder").hide(),n.find(".t3js-formengine-placeholder-formfield").show(),t&&n.find(".t3js-formengine-placeholder-formfield").find(":input").trigger("focus")):(n.find(".t3js-formengine-placeholder-placeholder").show(),n.find(".t3js-formengine-placeholder-formfield").hide())},reinitialize:function(){const e=document.querySelectorAll(".t3js-clearable");e.length>0&&import("@typo3/backend/input/clearable.js").then((function(){e.forEach((e=>e.clearable()))})),n.initializeNullNoPlaceholderCheckboxes(),n.initializeNullWithPlaceholderCheckboxes(),n.initializeLocalizationStateSelector(),n.initializeMinimumCharactersLeftViews(),n.initializeRemainingCharacterViews()},initializeLocalizationStateSelector:function(){document.querySelectorAll(".t3js-l10n-state-container").forEach((e=>{const t=e.closest(".t3js-formengine-field-item")?.querySelector("[data-formengine-input-name]");if(void 0===t)return;const n=e.querySelector('input[type="radio"]:checked').value;"parent"!==n&&"source"!==n||(t.disabled=!0)}))},hasChange:function(){const e=$('form[name="'+n.formName+'"] .has-change').length>0,t=$('[name^="data["].has-change').length>0;return e||t},preventExitIfNotSavedCallback:()=>{n.closeDocument()},preventFollowLinkIfNotSaved:function(e){return n.preventExitIfNotSaved((function(){window.location.href=e})),!1},preventExitIfNotSaved:function(e){if(e=e||n.preventExitIfNotSavedCallback,n.hasChange()){const t=TYPO3.lang["label.confirm.close_without_save.title"]||"Do you want to close without saving?",a=TYPO3.lang["label.confirm.close_without_save.content"]||"You currently have unsaved changes. Are you sure you want to discard these changes?",o=$("<input />").attr("type","hidden").attr("name","_saveandclosedok").attr("value","1"),i=[{text:TYPO3.lang["buttons.confirm.close_without_save.no"]||"No, I will continue editing",btnClass:"btn-default",name:"no"},{text:TYPO3.lang["buttons.confirm.close_without_save.yes"]||"Yes, discard my changes",btnClass:"btn-default",name:"yes"}];0===$(".has-error").length&&i.push({text:TYPO3.lang["buttons.confirm.save_and_close"]||"Save and close",btnClass:"btn-primary",name:"save",active:!0});const r=Modal.confirm(t,a,Severity.warning,i);r.addEventListener("button.clicked",(function(t){"no"===t.target.name?r.hideModal():"yes"===t.target.name?(r.hideModal(),e.call(null,!0)):"save"===t.target.name&&($("form[name="+n.formName+"]").append(o),r.hideModal(),n.saveDocument())}))}else e.call(null,!0)},preventSaveIfHasErrors:function(){if($(".has-error").length>0){const e=TYPO3.lang["label.alert.save_with_error.title"]||"You have errors in your form!",t=TYPO3.lang["label.alert.save_with_error.content"]||"Please check the form, there is at least one error in your form.",n=Modal.confirm(e,t,Severity.error,[{text:TYPO3.lang["buttons.alert.save_with_error.ok"]||"OK",btnClass:"btn-danger",name:"ok"}]);return n.addEventListener("button.clicked",(function(e){"ok"===e.target.name&&n.hideModal()})),!1}return!0},requestFormEngineUpdate:function(e){if(e){const e=Modal.advanced({title:TYPO3.lang["FormEngine.refreshRequiredTitle"],content:TYPO3.lang["FormEngine.refreshRequiredContent"],severity:Severity.warning,staticBackdrop:!0,buttons:[{text:TYPO3.lang["button.cancel"]||"Cancel",active:!0,btnClass:"btn-default",name:"cancel",trigger:()=>{e.hideModal()}},{text:TYPO3.lang["button.ok"]||"OK",btnClass:"btn-"+Severity.getCssClass(Severity.warning),name:"ok",trigger:()=>{n.closeModalsRecursive(),n.saveDocument()}}]})}else n.saveDocument()},processOnFieldChange:function(e,n){e.forEach((e=>{const a=t.get(e.name);a instanceof Function&&a.call(null,e.data||null,n)}))},registerOnFieldChangeHandler:function(e,n){t.has(e)&&console.warn("Handler for onFieldChange name `"+e+"` has been overridden."),t.set(e,n)},closeModalsRecursive:function(){void 0!==Modal.currentModal&&null!==Modal.currentModal&&(Modal.currentModal.addEventListener("typo3-modal-hidden",(function(){n.closeModalsRecursive()})),Modal.currentModal.hideModal())},previewAction:function(e,t){t=t||n.previewActionCallback;const a=e.currentTarget.href,o="isNew"in e.target.dataset,i=$("<input />").attr("type","hidden").attr("name","_savedokview").attr("value","1");n.hasChange()?n.showPreviewModal(a,o,i,t):($("form[name="+n.formName+"]").append(i),window.open("","newTYPO3frontendWindow"),document.editform.submit())},previewActionCallback:function(e,t,a){switch(Modal.dismiss(),e){case"discard":const e=window.open(t,"newTYPO3frontendWindow");e.focus(),Utility.urlsPointToSameServerSideResource(e.location.href,t)&&e.location.reload();break;case"save":$("form[name="+n.formName+"]").append($(a)),window.open("","newTYPO3frontendWindow"),n.saveDocument()}},showPreviewModal:function(e,t,n,a){const o=TYPO3.lang["label.confirm.view_record_changed.title"]||"Do you want to save before viewing?",i={text:TYPO3.lang["buttons.confirm.view_record_changed.cancel"]||"Cancel",btnClass:"btn-default",name:"cancel"},r={text:TYPO3.lang["buttons.confirm.view_record_changed.no-save"]||"View without changes",btnClass:"btn-default",name:"discard"},c={text:TYPO3.lang["buttons.confirm.view_record_changed.save"]||"Save changes and view",btnClass:"btn-primary",name:"save",active:!0};let l=[],s="";t?(l=[i,c],s=TYPO3.lang["label.confirm.view_record_changed.content.is-new-page"]||"You need to save your changes before viewing the page. Do you want to save and view them now?"):(l=[i,r,c],s=TYPO3.lang["label.confirm.view_record_changed.content"]||"You currently have unsaved changes. You can either discard these changes or save and view them.");const d=Modal.confirm(o,s,Severity.info,l);d.addEventListener("button.clicked",(function(t){a(t.target.name,e,n,d)}))},newAction:function(e,t){t=t||n.newActionCallback;const a=$("<input />").attr("type","hidden").attr("name","_savedoknew").attr("value","1"),o="isNew"in e.target.dataset;n.hasChange()?n.showNewModal(o,a,t):($("form[name="+n.formName+"]").append(a),document.editform.submit())},newActionCallback:function(e,t){const a=$("form[name="+n.formName+"]");switch(Modal.dismiss(),e){case"no":a.append(t),document.editform.submit();break;case"yes":a.append(t),n.saveDocument()}},showNewModal:function(e,t,n){const a=TYPO3.lang["label.confirm.new_record_changed.title"]||"Do you want to save before adding?",o=TYPO3.lang["label.confirm.new_record_changed.content"]||"You need to save your changes before creating a new record. Do you want to save and create now?";let i=[];const r={text:TYPO3.lang["buttons.confirm.new_record_changed.cancel"]||"Cancel",btnClass:"btn-default",name:"cancel"},c={text:TYPO3.lang["buttons.confirm.new_record_changed.no"]||"No, just add",btnClass:"btn-default",name:"no"},l={text:TYPO3.lang["buttons.confirm.new_record_changed.yes"]||"Yes, save and create now",btnClass:"btn-primary",name:"yes",active:!0};i=e?[r,l]:[r,c,l];Modal.confirm(a,o,Severity.info,i).addEventListener("button.clicked",(function(e){n(e.target.name,t)}))},duplicateAction:function(e,t){t=t||n.duplicateActionCallback;const a=$("<input />").attr("type","hidden").attr("name","_duplicatedoc").attr("value","1"),o="isNew"in e.target.dataset;n.hasChange()?n.showDuplicateModal(o,a,t):($("form[name="+n.formName+"]").append(a),document.editform.submit())},duplicateActionCallback:function(e,t){const a=$("form[name="+n.formName+"]");switch(Modal.dismiss(),e){case"no":a.append(t),document.editform.submit();break;case"yes":a.append(t),n.saveDocument()}},showDuplicateModal:function(e,t,n){const a=TYPO3.lang["label.confirm.duplicate_record_changed.title"]||"Do you want to save before duplicating this record?",o=TYPO3.lang["label.confirm.duplicate_record_changed.content"]||"You currently have unsaved changes. Do you want to save your changes before duplicating this record?";let i=[];const r={text:TYPO3.lang["buttons.confirm.duplicate_record_changed.cancel"]||"Cancel",btnClass:"btn-default",name:"cancel"},c={text:TYPO3.lang["buttons.confirm.duplicate_record_changed.no"]||"No, just duplicate the original",btnClass:"btn-default",name:"no"},l={text:TYPO3.lang["buttons.confirm.duplicate_record_changed.yes"]||"Yes, save and duplicate this record",btnClass:"btn-primary",name:"yes",active:!0};i=e?[r,l]:[r,c,l];Modal.confirm(a,o,Severity.info,i).addEventListener("button.clicked",(function(e){n(e.target.name,t)}))},deleteAction:function(e,t){t=t||n.deleteActionCallback;const a=$(e.target);n.showDeleteModal(a,t)},deleteActionCallback:function(e,t){Modal.dismiss(),"yes"===e&&n.invokeRecordDeletion(t)},showDeleteModal:function(e,t){const n=TYPO3.lang["label.confirm.delete_record.title"]||"Delete this record?";let a=(TYPO3.lang["label.confirm.delete_record.content"]||"Are you sure you want to delete the record '%s'?").replace("%s",e.data("record-info"));e.data("reference-count-message")&&(a+="\n"+e.data("reference-count-message")),e.data("translation-count-message")&&(a+="\n"+e.data("translation-count-message"));Modal.confirm(n,a,Severity.warning,[{text:TYPO3.lang["buttons.confirm.delete_record.no"]||"Cancel",btnClass:"btn-default",name:"no"},{text:TYPO3.lang["buttons.confirm.delete_record.yes"]||"Yes, delete this record",btnClass:"btn-warning",name:"yes",active:!0}]).addEventListener("button.clicked",(function(n){t(n.target.name,e)}))},enableOptGroup:function(e){const t=e.parentElement;t instanceof HTMLOptGroupElement&&t.querySelectorAll("option:not([hidden]):not([disabled]):not(.hidden)").length&&(t.hidden=!1,t.disabled=!1,t.classList.remove("hidden"))},closeDocument:function(){document.editform.closeDoc.value=1,n.dispatchSubmitEvent(),document.editform.submit()},saveDocument:function(){document.editform.doSave.value=1,n.dispatchSubmitEvent(),document.editform.submit()},dispatchSubmitEvent:function(){const e=document.createEvent("Event");e.initEvent("submit",!1,!0),document.editform.dispatchEvent(e)},initialize:function(e){n.browserUrl=e,DocumentService.ready().then((()=>{n.initializeEvents(),n.Validation.initialize(),n.reinitialize(),$("#t3js-ui-block").remove()}))},invokeRecordDeletion:function(e){window.location.href=e.attr("href")}};if(void 0!==TYPO3.settings.RequireJS&&void 0!==TYPO3.settings.RequireJS.PostInitializationModules["TYPO3/CMS/Backend/FormEngine"])for(const e of TYPO3.settings.RequireJS.PostInitializationModules["TYPO3/CMS/Backend/FormEngine"])window.require([e]);return TYPO3.FormEngine=n,n}()); \ No newline at end of file diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/form-engine/field-control/password-generator.js b/typo3/sysext/backend/Resources/Public/JavaScript/form-engine/field-control/password-generator.js index 9ee0e030e8e5..81c156894018 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/form-engine/field-control/password-generator.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/form-engine/field-control/password-generator.js @@ -10,4 +10,4 @@ * * The TYPO3 project - inspiring people to share! */ -import DocumentService from"@typo3/core/document-service.js";import SecurityUtility from"@typo3/core/security-utility.js";import FormEngineValidation from"@typo3/backend/form-engine-validation.js";import AjaxRequest from"@typo3/core/ajax/ajax-request.js";import Notification from"@typo3/backend/notification.js";class PasswordGenerator{constructor(e){this.securityUtility=null,this.controlElement=null,this.humanReadableField=null,this.hiddenField=null,this.passwordRules=null,this.securityUtility=new SecurityUtility,DocumentService.ready().then((()=>{if(this.controlElement=document.getElementById(e),this.humanReadableField=document.querySelector('input[data-formengine-input-name="'+this.controlElement.dataset.itemName+'"]'),this.hiddenField=document.querySelector('input[name="'+this.controlElement.dataset.itemName+'"]'),this.passwordRules=JSON.parse(this.controlElement.dataset.passwordRules||"{}"),!this.controlElement.dataset.allowEdit&&(this.humanReadableField.disabled=!0,this.humanReadableField.readOnly=!0,this.humanReadableField.isClearable||this.humanReadableField.classList.contains("t3js-clearable"))){this.humanReadableField.classList.remove("t3js-clearable");const e=this.humanReadableField.closest("div.form-control-clearable");if(e){e.classList.remove("form-control-clearable");const t=e.querySelector("button.close");t&&e.removeChild(t)}}this.controlElement.addEventListener("click",this.generatePassword.bind(this))}))}generatePassword(e){e.preventDefault(),new AjaxRequest(TYPO3.settings.ajaxUrls.password_generate).post({passwordRules:this.passwordRules}).then((async e=>{const t=await e.resolve();!0===t.success?(this.humanReadableField.type="text",this.humanReadableField.value=t.password,this.humanReadableField.dispatchEvent(new Event("change")),this.humanReadableField.value=this.hiddenField.value,FormEngineValidation.validateField(this.humanReadableField),FormEngineValidation.markFieldAsChanged(this.humanReadableField)):Notification.warning(t.message||"No password was generated")})).catch((()=>{Notification.error("Password could not be generated")}))}}export default PasswordGenerator; \ No newline at end of file +import DocumentService from"@typo3/core/document-service.js";import SecurityUtility from"@typo3/core/security-utility.js";import FormEngineValidation from"@typo3/backend/form-engine-validation.js";import AjaxRequest from"@typo3/core/ajax/ajax-request.js";import Notification from"@typo3/backend/notification.js";class PasswordGenerator{constructor(e){this.securityUtility=null,this.controlElement=null,this.humanReadableField=null,this.hiddenField=null,this.passwordRules=null,this.securityUtility=new SecurityUtility,DocumentService.ready().then((()=>{if(this.controlElement=document.getElementById(e),this.humanReadableField=document.querySelector('input[data-formengine-input-name="'+this.controlElement.dataset.itemName+'"]'),this.hiddenField=document.querySelector('input[name="'+this.controlElement.dataset.itemName+'"]'),this.passwordRules=JSON.parse(this.controlElement.dataset.passwordRules||"{}"),!this.controlElement.dataset.allowEdit&&(this.humanReadableField.disabled=!0,this.humanReadableField.readOnly=!0,this.humanReadableField.isClearable||this.humanReadableField.classList.contains("t3js-clearable"))){this.humanReadableField.classList.remove("t3js-clearable");const e=this.humanReadableField.closest("div.form-control-clearable-wrapper");if(e){e.classList.remove("form-control-clearable");const t=e.querySelector("button.close");t&&e.removeChild(t)}}this.controlElement.addEventListener("click",this.generatePassword.bind(this))}))}generatePassword(e){e.preventDefault(),new AjaxRequest(TYPO3.settings.ajaxUrls.password_generate).post({passwordRules:this.passwordRules}).then((async e=>{const t=await e.resolve();!0===t.success?(this.humanReadableField.type="text",this.humanReadableField.value=t.password,this.humanReadableField.dispatchEvent(new Event("change")),this.humanReadableField.value=this.hiddenField.value,FormEngineValidation.validateField(this.humanReadableField),FormEngineValidation.markFieldAsChanged(this.humanReadableField)):Notification.warning(t.message||"No password was generated")})).catch((()=>{Notification.error("Password could not be generated")}))}}export default PasswordGenerator; \ No newline at end of file diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/input/clearable.js b/typo3/sysext/backend/Resources/Public/JavaScript/input/clearable.js index 44ff54b0714b..5caddf26eb0a 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/input/clearable.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/input/clearable.js @@ -10,4 +10,4 @@ * * The TYPO3 project - inspiring people to share! */ -class Clearable{constructor(){"function"!=typeof HTMLInputElement.prototype.clearable&&this.registerClearable()}static createCloseButton(){const e=document.createElement("button");return e.type="button",e.tabIndex=-1,e.innerHTML='<span class="t3js-icon icon icon-size-small icon-state-default icon-actions-close" data-identifier="actions-close">\n <span class="icon-markup">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">\n <path\n d="M11.9 5.5L9.4 8l2.5 2.5c.2.2.2.5 0\n .7l-.7.7c-.2.2-.5.2-.7 0L8 9.4l-2.5 2.5c-.2.2-.5.2-.7\n 0l-.7-.7c-.2-.2-.2-.5 0-.7L6.6 8 4.1 5.5c-.2-.2-.2-.5\n 0-.7l.7-.7c.2-.2.5-.2.7 0L8 6.6l2.5-2.5c.2-.2.5-.2.7\n 0l.7.7c.2.2.2.5 0 .7z"\n class="icon-color"/>\n </svg>\n </span>\n </span>',e.style.visibility="hidden",e.classList.add("close"),e}registerClearable(){HTMLInputElement.prototype.clearable=function(e={}){if(this.isClearable)return;if("object"!=typeof e)throw new Error("Passed options must be an object, "+typeof e+" given");const t=document.createElement("div");t.classList.add("form-control-clearable"),this.parentNode.insertBefore(t,this),t.appendChild(this);const n=Clearable.createCloseButton(),s=()=>{n.style.visibility=0===this.value.length?"hidden":"visible"};n.addEventListener("click",(t=>{t.preventDefault(),this.value="","function"==typeof e.onClear&&e.onClear(this),this.dispatchEvent(new Event("change",{bubbles:!0,cancelable:!0})),s()})),t.appendChild(n),this.addEventListener("focus",s),this.addEventListener("keyup",s),s(),this.isClearable=!0}}}export default new Clearable; \ No newline at end of file +class Clearable{constructor(){"function"!=typeof HTMLInputElement.prototype.clearable&&this.registerClearable()}static createCloseButton(){const e=document.createElement("button");return e.type="button",e.tabIndex=-1,e.innerHTML='<span class="t3js-icon icon icon-size-small icon-state-default icon-actions-close" data-identifier="actions-close">\n <span class="icon-markup">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">\n <path\n d="M11.9 5.5L9.4 8l2.5 2.5c.2.2.2.5 0\n .7l-.7.7c-.2.2-.5.2-.7 0L8 9.4l-2.5 2.5c-.2.2-.5.2-.7\n 0l-.7-.7c-.2-.2-.2-.5 0-.7L6.6 8 4.1 5.5c-.2-.2-.2-.5\n 0-.7l.7-.7c.2-.2.5-.2.7 0L8 6.6l2.5-2.5c.2-.2.5-.2.7\n 0l.7.7c.2.2.2.5 0 .7z"\n class="icon-color"/>\n </svg>\n </span>\n </span>',e.style.visibility="hidden",e.classList.add("close"),e}registerClearable(){HTMLInputElement.prototype.clearable=function(e={}){if(this.isClearable)return;if("object"!=typeof e)throw new Error("Passed options must be an object, "+typeof e+" given");this.classList.add("form-control-clearable");const t=document.createElement("div");t.classList.add("form-control-clearable-wrapper"),this.parentNode.insertBefore(t,this),t.appendChild(this);const n=Clearable.createCloseButton(),s=()=>{n.style.visibility=0===this.value.length?"hidden":"visible"};n.addEventListener("click",(t=>{t.preventDefault(),this.value="","function"==typeof e.onClear&&e.onClear(this),this.dispatchEvent(new Event("change",{bubbles:!0,cancelable:!0})),s()})),t.appendChild(n),this.addEventListener("focus",s),this.addEventListener("keyup",s),s(),this.isClearable=!0}}}export default new Clearable; \ No newline at end of file diff --git a/typo3/sysext/belog/Resources/Private/Partials/Content/Filter.html b/typo3/sysext/belog/Resources/Private/Partials/Content/Filter.html index 958079076e5b..3edf0b5c069c 100644 --- a/typo3/sysext/belog/Resources/Private/Partials/Content/Filter.html +++ b/typo3/sysext/belog/Resources/Private/Partials/Content/Filter.html @@ -5,9 +5,9 @@ data-namespace-typo3-fluid="true"> <f:form object="{constraint}" action="list" name="constraint" class="belog-filter-form"> - <div class="row row-cols-auto align-items-end g-3 mb-4"> + <div class="form-row"> - <div class="col"> + <div class="form-group"> <label for="belog-users" class="form-label"><f:translate key="users" /></label> <f:form.select property="userOrGroup" @@ -17,7 +17,7 @@ /> </div> - <div class="col"> + <div class="form-group"> <label for="belog-max" class="form-label"><f:translate key="max" /></label> <f:form.select property="number" @@ -28,7 +28,7 @@ </div> <f:if condition="{showWorkspaceSelector}"> - <div class="col"> + <div class="form-group"> <label for="belog-workspaces" class="form-label"><f:translate key="workspace" /></label> <f:form.select property="workspaceUid" @@ -39,7 +39,7 @@ </div> </f:if> - <div class="col"> + <div class="form-group"> <label for="belog-pageId" class="form-label"><f:translate key="chLog_menuPageId" /></label> <div class="input-group"> <f:form.textfield @@ -62,7 +62,7 @@ </div> <f:if condition="{pageId}"> - <div class="col"> + <div class="form-group"> <label for="belog-depth" class="form-label"><f:translate key="chLog_menuDepth" /></label> <f:form.select property="depth" @@ -73,7 +73,7 @@ </div> </f:if> - <div class="col"> + <div class="form-group"> <label for="belog-channel" class="form-label"><f:translate key="channel" /></label> <f:form.select property="channel" @@ -86,7 +86,7 @@ /> </div> - <div class="col"> + <div class="form-group"> <label for="belog-level" class="form-label"><f:translate key="levels" /></label> <f:form.select property="level" @@ -99,7 +99,7 @@ /> </div> - <div class="col"> + <div class="form-group"> <label for="manualDateStart" class="form-label"><f:translate key="LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:from" /></label> <div class="input-group"> <f:form.textfield @@ -107,7 +107,7 @@ value="{f:if(condition: constraint.manualDateStart, then: \"{f:format.date(format:'{settings.dateTimeFormat}', date: '{constraint.manualDateStart}')}\")}" id="manualDateStart" additionalAttributes="{'autocomplete': 'off'}" - class="form-control t3js-datetimepicker t3js-clearable" + class="form-control form-control-clearable t3js-datetimepicker t3js-clearable" data="{date-type: 'datetime'}" /> <f:form.hidden @@ -120,7 +120,7 @@ </div> </div> - <div class="col"> + <div class="form-group"> <label for="manualDateStop" class="form-label"><f:translate key="LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:to" /></label> <div class="input-group"> <f:form.textfield @@ -128,7 +128,7 @@ value="{f:format.date(format:'{settings.dateTimeFormat}', date: '{constraint.manualDateStop}')}" additionalAttributes="{'autocomplete': 'off'}" id="manualDateStop" - class="form-control t3js-datetimepicker t3js-clearable" + class="form-control form-control-clearable t3js-datetimepicker t3js-clearable" data="{date-type: 'datetime'}" /> <f:form.hidden @@ -141,8 +141,8 @@ </div> </div> - <div class="col"> - <f:form.button type="submit" name="operation" value="filter" class="btn btn-light">{f:translate(key: 'set')}</f:form.button> + <div class="form-group align-self-end"> + <f:form.button type="submit" name="operation" value="filter" class="btn btn-default">{f:translate(key: 'set')}</f:form.button> <f:form.button type="submit" name="operation" value="reset-filters" class="btn btn-link">{f:translate(key: 'reset')}</f:form.button> </div> </div> diff --git a/typo3/sysext/beuser/Resources/Private/Partials/BackendUser/Filter.html b/typo3/sysext/beuser/Resources/Private/Partials/BackendUser/Filter.html index ca3c5fa0939a..a7d1fdc865ba 100644 --- a/typo3/sysext/beuser/Resources/Private/Partials/BackendUser/Filter.html +++ b/typo3/sysext/beuser/Resources/Private/Partials/BackendUser/Filter.html @@ -4,8 +4,8 @@ > <f:form action="index" objectName="demand" object="{demand}"> - <div class="row row-cols-auto align-items-end g-3 mb-4"> - <div class="col"> + <div class="form-row"> + <div class="form-group"> <label for="tx_Beuser_username" class="form-label"><f:translate key="userName">Username</f:translate></label> <f:form.textfield id="tx_Beuser_username" @@ -13,7 +13,7 @@ property="userName" /> </div> - <div class="col"> + <div class="form-group"> <label for="tx_Beuser_usertype" class="form-label"><f:translate key="admin">Admin</f:translate></label> <f:form.select id="tx_Beuser_usertype" @@ -22,7 +22,7 @@ options="{0: '{f:translate(key:\"both\")}', 1: '{f:translate(key:\"adminOnly\")}', 2: '{f:translate(key:\"normalUserOnly\")}'}" /> </div> - <div class="col"> + <div class="form-group"> <label for="tx_Beuser_status" class="form-label"><f:translate key="status">Status</f:translate></label> <f:form.select id="tx_Beuser_status" @@ -31,7 +31,7 @@ options="{0: '{f:translate(key:\"both\")}', 1: '{f:translate(key:\"activeOnly\")}', 2: '{f:translate(key:\"inactiveOnly\")}'}" /> </div> - <div class="col"> + <div class="form-group"> <label for="tx_Beuser_logins" class="form-label"><f:translate key="login">Login</f:translate></label> <f:form.select id="tx_Beuser_logins" @@ -40,7 +40,7 @@ options="{0: '{f:translate(key:\"both\")}', 1: '{f:translate(key:\"loginBefore\")}', 2: '{f:translate(key:\"neverLoggedIn\")}'}" /> </div> - <div class="col"> + <div class="form-group"> <label for="tx_beuser_backendUserGroup" class="form-label"><f:translate key="backendUserGroup">User Group</f:translate></label> <f:form.select id="tx_beuser_backendUserGroup" @@ -51,8 +51,8 @@ optionValueField="uid" /> </div> - <div class="col"> - <f:form.button type="submit" name="operation" value="filter" class="btn btn-light">{f:translate(key: 'filter')}</f:form.button> + <div class="form-group align-self-end"> + <f:form.button type="submit" name="operation" value="filter" class="btn btn-default">{f:translate(key: 'filter')}</f:form.button> <f:form.button type="submit" name="operation" value="reset-filters" class="btn btn-link">{f:translate(key: 'reset')}</f:form.button> </div> </div> diff --git a/typo3/sysext/beuser/Resources/Private/Partials/BackendUserGroup/Filter.html b/typo3/sysext/beuser/Resources/Private/Partials/BackendUserGroup/Filter.html index a5d6dc2c6fa3..8c3669940d10 100644 --- a/typo3/sysext/beuser/Resources/Private/Partials/BackendUserGroup/Filter.html +++ b/typo3/sysext/beuser/Resources/Private/Partials/BackendUserGroup/Filter.html @@ -4,16 +4,16 @@ > <f:form action="groups" objectName="userGroupDto" object="{userGroupDto}"> - <div class="row row-cols-auto align-items-end g-3 mb-4"> - <div class="col"> + <div class="form-row"> + <div class="form-group"> <label for="tx_Beugroups_title" class="form-label"><f:translate key="userGroupTitle" /></label> <f:form.textfield id="tx_Beugroups_title" class="form-control" property="title"/> </div> - <div class="col"> - <f:form.button type="submit" name="operation" value="filter" class="btn btn-light">{f:translate(key: 'filter')}</f:form.button> + <div class="form-group align-self-end"> + <f:form.button type="submit" name="operation" value="filter" class="btn btn-default">{f:translate(key: 'filter')}</f:form.button> <f:form.button type="submit" name="operation" value="reset-filters" class="btn btn-link">{f:translate(key: 'reset')}</f:form.button> </div> </div> diff --git a/typo3/sysext/beuser/Resources/Private/Templates/BackendUser/List.html b/typo3/sysext/beuser/Resources/Private/Templates/BackendUser/List.html index 3f7a488c4d54..1a4b083ae2c2 100644 --- a/typo3/sysext/beuser/Resources/Private/Templates/BackendUser/List.html +++ b/typo3/sysext/beuser/Resources/Private/Templates/BackendUser/List.html @@ -55,16 +55,14 @@ </tbody> </table> </div> - <div class="mb-4"> - <f:link.action action="compare" title="{f:translate(key: 'compareUserList', default: 'Compare user list')}" class="btn btn-default t3js-acceptance-compare"> - <core:icon identifier="actions-code-compare" /> - {f:translate(key: 'compareUserList', default: 'Compare user list')} - </f:link.action> - <f:link.action action="removeAllFromCompareList" class="btn btn-default"> - <core:icon identifier="actions-selection-delete" /> - {f:translate(key: 'clearCompareList')} - </f:link.action> - </div> + <f:link.action action="compare" title="{f:translate(key: 'compareUserList', default: 'Compare user list')}" class="btn btn-default t3js-acceptance-compare"> + <core:icon identifier="actions-code-compare" /> + {f:translate(key: 'compareUserList', default: 'Compare user list')} + </f:link.action> + <f:link.action action="removeAllFromCompareList" class="btn btn-default"> + <core:icon identifier="actions-selection-delete" /> + {f:translate(key: 'clearCompareList')} + </f:link.action> <h2>{f:translate(key: 'section.allUsers', default: 'All backend users')}</h2> </f:if> diff --git a/typo3/sysext/beuser/Resources/Private/Templates/BackendUser/Show.html b/typo3/sysext/beuser/Resources/Private/Templates/BackendUser/Show.html index c7262185449d..a6bd288eb474 100644 --- a/typo3/sysext/beuser/Resources/Private/Templates/BackendUser/Show.html +++ b/typo3/sysext/beuser/Resources/Private/Templates/BackendUser/Show.html @@ -76,44 +76,44 @@ <div class="row"> <div class="col-lg-4"> - <h2><f:translate key="LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:be_groups.subgroup" /></h2> + <h2 class="headline-spaced"><f:translate key="LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:be_groups.subgroup" /></h2> <f:render partial="Compare/Information" section="groups" arguments="{groups:data.groups}"/> </div> <div class="col-lg-4"> - <h2><f:translate key="allowedLanguages" /></h2> + <h2 class="headline-spaced"><f:translate key="allowedLanguages" /></h2> <f:render partial="Compare/Information" section="languages" arguments="{languages:data.languages}"/> </div> <div class="col-lg-4"> - <h2><f:translate key="dbMountPoints" /></h2> + <h2 class="headline-spaced"><f:translate key="dbMountPoints" /></h2> <f:render partial="Compare/Information" section="dbMounts" arguments="{dbMounts:data.dbMounts}"/> - <h2><f:translate key="fileMounts" /></h2> + <h2 class="headline-spaced"><f:translate key="fileMounts" /></h2> <f:render partial="Compare/Information" section="fileMounts" arguments="{fileMounts:data.fileMounts}"/> </div> </div> <div class="row"> <div class="col-md-6"> - <h2>{f:translate(key:'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:be_groups.pagetypes_select')}</h2> + <h2 class="headline-spaced">{f:translate(key:'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:be_groups.pagetypes_select')}</h2> <f:render partial="Compare/Information" section="pageTypes" arguments="{pageTypes:data.pageTypes}" /> - <h2><f:translate key="permissions" /></h2> + <h2 class="headline-spaced"><f:translate key="permissions" /></h2> <f:render partial="Compare/Information" section="modules" arguments="{showTitle:1,modules:data.modules}"/> - <h2>{f:translate(key:'compare.tables')}</h2> + <h2 class="headline-spaced">{f:translate(key:'compare.tables')}</h2> <f:render partial="Compare/Information" section="tables" arguments="{showTitle:1,tables:data.tables}"/> - <h2>{f:translate(key:'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:category_perms')}</h2> + <h2 class="headline-spaced">{f:translate(key:'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:category_perms')}</h2> <f:render partial="Compare/Information" section="categories" arguments="{categories:data.categories}"/> - <h2>{f:translate(key:'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:TSconfig')}</h2> + <h2 class="headline-spaced">{f:translate(key:'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:TSconfig')}</h2> <f:render partial="Compare/Information" section="tsconfig" arguments="{tsconfig:data.tsconfig,id:data.user.uid}" /> </div> <div class="col-md-6"> - <h2>{f:translate(key:'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:be_groups.non_exclude_fields')}</h2> + <h2 class="headline-spaced">{f:translate(key:'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:be_groups.non_exclude_fields')}</h2> <f:render partial="Compare/Information" section="nonExcludeFields" arguments="{nonExcludeFields:data.non_exclude_fields, id:data.user.uid}"/> - <h2>{f:translate(key:'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:be_groups.fileoper_perms')}</h2> + <h2 class="headline-spaced">{f:translate(key:'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:be_groups.fileoper_perms')}</h2> <f:render partial="Compare/Information" section="fileFolderPermissions" arguments="{fileFolderPermissions:data.fileFolderPermissions}" /> </div> </div> diff --git a/typo3/sysext/beuser/Resources/Private/Templates/BackendUserGroup/List.html b/typo3/sysext/beuser/Resources/Private/Templates/BackendUserGroup/List.html index 30d31e70132c..0627a08c539c 100644 --- a/typo3/sysext/beuser/Resources/Private/Templates/BackendUserGroup/List.html +++ b/typo3/sysext/beuser/Resources/Private/Templates/BackendUserGroup/List.html @@ -44,16 +44,14 @@ </tbody> </table> </div> - <div class="mb-4"> - <f:link.action action="compareGroups" class="btn btn-default t3js-acceptance-compare"> - <core:icon identifier="actions-code-compare" /> - {f:translate(key: 'compareBackendUsersGroups')} - </f:link.action> - <f:link.action action="removeAllGroupsFromCompareList" class="btn btn-default"> - <core:icon identifier="actions-selection-delete" /> - {f:translate(key: 'clearCompareList')} - </f:link.action> - </div> + <f:link.action action="compareGroups" class="btn btn-default t3js-acceptance-compare"> + <core:icon identifier="actions-code-compare" /> + {f:translate(key: 'compareBackendUsersGroups')} + </f:link.action> + <f:link.action action="removeAllGroupsFromCompareList" class="btn btn-default"> + <core:icon identifier="actions-selection-delete" /> + {f:translate(key: 'clearCompareList')} + </f:link.action> <h2>{f:translate(key: 'section.allUserGroups', default: 'All backend user groups')}</h2> </f:if> diff --git a/typo3/sysext/beuser/Resources/Private/Templates/Permission/Edit.html b/typo3/sysext/beuser/Resources/Private/Templates/Permission/Edit.html index b6bd244b9b9e..1ffac442f909 100644 --- a/typo3/sysext/beuser/Resources/Private/Templates/Permission/Edit.html +++ b/typo3/sysext/beuser/Resources/Private/Templates/Permission/Edit.html @@ -22,17 +22,17 @@ <form action="{formAction}" method="post" name="editform" id="PermissionControllerEdit"> - <div class="row row-cols-auto align-items-end g-3 mb-4"> - <div class="col"> - <label for="selectOwner"><f:translate key="LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:Owner" /></label> + <div class="form-row"> + <div class="form-group"> + <label class="form-label" for="selectOwner"><f:translate key="LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:Owner" /></label> <select class="form-select" name="data[pages][{id}][perms_userid]" id="selectOwner"> <f:for each="{beUserData}" key="userId" as="user"> <option value="{userId}" {f:if(condition: '{userId} == {currentBeUser}', then: 'selected')}>{user}</option> </f:for> </select> </div> - <div class="col"> - <label for="selectGroup"><f:translate key="LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:Group" /></label> + <div class="form-group"> + <label class="form-label" for="selectGroup"><f:translate key="LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:Group" /></label> <f:if condition="{f:count(subject:beGroupData)} > 1"> <f:then> <select class="form-select" name="data[pages][{id}][perms_groupid]" id="selectGroup"> @@ -46,8 +46,8 @@ </f:else> </f:if> </div> - <div class="col"> - <label for="recursionLevel"><f:translate key="LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:Depth" /></label> + <div class="form-group"> + <label class="form-label" for="recursionLevel"><f:translate key="LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:Depth" /></label> <select class="form-select" name="mirror[pages][{id}]" id="recursionLevel"> <f:for each="{recursiveSelectOptions}" key="depth" as="depthLabel"> <option value="{depth}" {f:if(condition: '{depth} == {currentBeUser}', then: 'selected')}>{depthLabel}</option> @@ -71,27 +71,87 @@ <tbody> <tr> <td><strong><f:translate key="LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:Owner" /></strong></td> - <td><input type="checkbox" name="check[perms_user][]" value="{base ^ 0}" data-check-change-permissions="check[perms_user],data[pages][{id}][perms_user]" /></td> - <td><input type="checkbox" name="check[perms_user][]" value="{base ^ 4}" data-check-change-permissions="check[perms_user],data[pages][{id}][perms_user]" /></td> - <td><input type="checkbox" name="check[perms_user][]" value="{base ^ 1}" data-check-change-permissions="check[perms_user],data[pages][{id}][perms_user]" /></td> - <td><input type="checkbox" name="check[perms_user][]" value="{base ^ 2}" data-check-change-permissions="check[perms_user],data[pages][{id}][perms_user]" /></td> - <td><input type="checkbox" name="check[perms_user][]" value="{base ^ 3}" data-check-change-permissions="check[perms_user],data[pages][{id}][perms_user]" /></td> + <td> + <div class="form-check form-check-type-toggle"> + <input class="form-check-input" type="checkbox" name="check[perms_user][]" value="{base ^ 0}" data-check-change-permissions="check[perms_user],data[pages][{id}][perms_user]" /> + </div> + </td> + <td> + <div class="form-check form-check-type-toggle"> + <input class="form-check-input" type="checkbox" name="check[perms_user][]" value="{base ^ 4}" data-check-change-permissions="check[perms_user],data[pages][{id}][perms_user]" /> + </div> + </td> + <td> + <div class="form-check form-check-type-toggle"> + <input class="form-check-input" type="checkbox" name="check[perms_user][]" value="{base ^ 1}" data-check-change-permissions="check[perms_user],data[pages][{id}][perms_user]" /> + </div> + </td> + <td> + <div class="form-check form-check-type-toggle"> + <input class="form-check-input" type="checkbox" name="check[perms_user][]" value="{base ^ 2}" data-check-change-permissions="check[perms_user],data[pages][{id}][perms_user]" /> + </div> + </td> + <td> + <div class="form-check form-check-type-toggle"> + <input class="form-check-input" type="checkbox" name="check[perms_user][]" value="{base ^ 3}" data-check-change-permissions="check[perms_user],data[pages][{id}][perms_user]" /> + </div> + </td> </tr> <tr> <td><strong><f:translate key="LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:Group" /></strong></td> - <td><input type="checkbox" name="check[perms_group][]" value="{base ^ 0}" data-check-change-permissions="check[perms_group],data[pages][{id}][perms_group]" /></td> - <td><input type="checkbox" name="check[perms_group][]" value="{base ^ 4}" data-check-change-permissions="check[perms_group],data[pages][{id}][perms_group]" /></td> - <td><input type="checkbox" name="check[perms_group][]" value="{base ^ 1}" data-check-change-permissions="check[perms_group],data[pages][{id}][perms_group]" /></td> - <td><input type="checkbox" name="check[perms_group][]" value="{base ^ 2}" data-check-change-permissions="check[perms_group],data[pages][{id}][perms_group]" /></td> - <td><input type="checkbox" name="check[perms_group][]" value="{base ^ 3}" data-check-change-permissions="check[perms_group],data[pages][{id}][perms_group]" /></td> + <td> + <div class="form-check form-check-type-toggle"> + <input class="form-check-input" type="checkbox" name="check[perms_group][]" value="{base ^ 0}" data-check-change-permissions="check[perms_group],data[pages][{id}][perms_group]" /> + </div> + </td> + <td> + <div class="form-check form-check-type-toggle"> + <input class="form-check-input" type="checkbox" name="check[perms_group][]" value="{base ^ 4}" data-check-change-permissions="check[perms_group],data[pages][{id}][perms_group]" /> + </div> + </td> + <td> + <div class="form-check form-check-type-toggle"> + <input class="form-check-input" type="checkbox" name="check[perms_group][]" value="{base ^ 1}" data-check-change-permissions="check[perms_group],data[pages][{id}][perms_group]" /> + </div> + </td> + <td> + <div class="form-check form-check-type-toggle"> + <input class="form-check-input" type="checkbox" name="check[perms_group][]" value="{base ^ 2}" data-check-change-permissions="check[perms_group],data[pages][{id}][perms_group]" /> + </div> + </td> + <td> + <div class="form-check form-check-type-toggle"> + <input class="form-check-input" type="checkbox" name="check[perms_group][]" value="{base ^ 3}" data-check-change-permissions="check[perms_group],data[pages][{id}][perms_group]" /> + </div> + </td> </tr> <tr> <td><strong><f:translate key="LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:Everybody" /></strong></td> - <td><input type="checkbox" name="check[perms_everybody][]" value="{base ^ 0}" data-check-change-permissions="check[perms_everybody],data[pages][{id}][perms_everybody]" /></td> - <td><input type="checkbox" name="check[perms_everybody][]" value="{base ^ 4}" data-check-change-permissions="check[perms_everybody],data[pages][{id}][perms_everybody]" /></td> - <td><input type="checkbox" name="check[perms_everybody][]" value="{base ^ 1}" data-check-change-permissions="check[perms_everybody],data[pages][{id}][perms_everybody]" /></td> - <td><input type="checkbox" name="check[perms_everybody][]" value="{base ^ 2}" data-check-change-permissions="check[perms_everybody],data[pages][{id}][perms_everybody]" /></td> - <td><input type="checkbox" name="check[perms_everybody][]" value="{base ^ 3}" data-check-change-permissions="check[perms_everybody],data[pages][{id}][perms_everybody]" /></td> + <td> + <div class="form-check form-check-type-toggle"> + <input class="form-check-input" type="checkbox" name="check[perms_everybody][]" value="{base ^ 0}" data-check-change-permissions="check[perms_everybody],data[pages][{id}][perms_everybody]" /> + </div> + </td> + <td> + <div class="form-check form-check-type-toggle"> + <input class="form-check-input" type="checkbox" name="check[perms_everybody][]" value="{base ^ 4}" data-check-change-permissions="check[perms_everybody],data[pages][{id}][perms_everybody]" /> + </div> + </td> + <td> + <div class="form-check form-check-type-toggle"> + <input class="form-check-input" type="checkbox" name="check[perms_everybody][]" value="{base ^ 1}" data-check-change-permissions="check[perms_everybody],data[pages][{id}][perms_everybody]" /> + </div> + </td> + <td> + <div class="form-check form-check-type-toggle"> + <input class="form-check-input" type="checkbox" name="check[perms_everybody][]" value="{base ^ 2}" data-check-change-permissions="check[perms_everybody],data[pages][{id}][perms_everybody]" /> + </div> + </td> + <td> + <div class="form-check form-check-type-toggle"> + <input class="form-check-input" type="checkbox" name="check[perms_everybody][]" value="{base ^ 3}" data-check-change-permissions="check[perms_everybody],data[pages][{id}][perms_everybody]" /> + </div> + </td> </tr> </tbody> </table> diff --git a/typo3/sysext/core/Tests/Acceptance/Application/DbCheck/DbCheckModuleCest.php b/typo3/sysext/core/Tests/Acceptance/Application/DbCheck/DbCheckModuleCest.php index d5d98438e380..fd0c5447d465 100644 --- a/typo3/sysext/core/Tests/Acceptance/Application/DbCheck/DbCheckModuleCest.php +++ b/typo3/sysext/core/Tests/Acceptance/Application/DbCheck/DbCheckModuleCest.php @@ -94,11 +94,11 @@ final class DbCheckModuleCest { $this->goToPageAndSeeHeadline($I, 'Full search', 'Search whole Database'); $I->see('Search options', 'h2'); - $I->see('Result', 'h2'); // Fill in search phrase and check results $I->fillField('input[name="SET[sword]"]', 'styleguide demo group 1'); $I->click('Search All Records'); + $I->see('Result', 'h2'); $I->see('styleguide demo group 1', 'td'); $I->dontSee('styleguide demo group 2', 'td'); diff --git a/typo3/sysext/core/Tests/Acceptance/Application/RecordList/RecordDownloadCest.php b/typo3/sysext/core/Tests/Acceptance/Application/RecordList/RecordDownloadCest.php index b09d115a0ae6..676b42834a10 100644 --- a/typo3/sysext/core/Tests/Acceptance/Application/RecordList/RecordDownloadCest.php +++ b/typo3/sysext/core/Tests/Acceptance/Application/RecordList/RecordDownloadCest.php @@ -46,10 +46,10 @@ final class RecordDownloadCest $modalDialog->canSeeDialog(); $I->canSee('Download Page:', ModalDialog::$openedModalSelector . ' .modal-title'); $I->fillField(ModalDialog::$openedModalSelector . ' input[name="filename"]', 'test-download'); - $I->canSee('CSV options', ModalDialog::$openedModalSelector . ' .modal-body h5'); + $I->canSee('CSV options', ModalDialog::$openedModalSelector . ' .modal-body h2'); $I->selectOption(ModalDialog::$openedModalSelector . ' select[name="format"]', 'json'); - $I->dontSee('CSV options', ModalDialog::$openedModalSelector . ' .modal-body h5'); - $I->see('JSON options', ModalDialog::$openedModalSelector . ' .modal-body h5'); + $I->dontSee('CSV options', ModalDialog::$openedModalSelector . ' .modal-body h2'); + $I->see('JSON options', ModalDialog::$openedModalSelector . ' .modal-body h2'); $I->selectOption(ModalDialog::$openedModalSelector . ' select[name="json[meta]"]', 'full'); $I->click('button[name="download"]', ModalDialog::$openedModalButtonContainerSelector); $I->waitForElementNotVisible(ModalDialog::$openedModalSelector, 30); diff --git a/typo3/sysext/extensionmanager/Resources/Private/Templates/List/Distributions.html b/typo3/sysext/extensionmanager/Resources/Private/Templates/List/Distributions.html index 9098df63aa05..c15bc90dd2f2 100644 --- a/typo3/sysext/extensionmanager/Resources/Private/Templates/List/Distributions.html +++ b/typo3/sysext/extensionmanager/Resources/Private/Templates/List/Distributions.html @@ -21,12 +21,10 @@ <f:if condition="{enableDistributionsView}"> <f:then> <f:if condition="{showUnsuitableDistributions} == 0"> - <div class="row"> - <div class="col-sm-6"> - <f:form class="typo3-extensionmanager-unsuitable-dist" action="distributions" arguments="{showUnsuitableDistributions: 1}" > - <f:form.submit class="btn btn-default" value="{f:translate(key:'extensionList.showUnsuitableDistributions')}"/> - </f:form> - </div> + <div class="form-group"> + <f:form class="typo3-extensionmanager-unsuitable-dist" action="distributions" arguments="{showUnsuitableDistributions: 1}" > + <f:form.submit class="btn btn-default" value="{f:translate(key:'extensionList.showUnsuitableDistributions')}"/> + </f:form> </div> </f:if> <div class="card-container"> diff --git a/typo3/sysext/extensionmanager/Resources/Private/Templates/List/Index.html b/typo3/sysext/extensionmanager/Resources/Private/Templates/List/Index.html index 2bdd9c8b87bf..d8e4f19f4628 100644 --- a/typo3/sysext/extensionmanager/Resources/Private/Templates/List/Index.html +++ b/typo3/sysext/extensionmanager/Resources/Private/Templates/List/Index.html @@ -20,14 +20,14 @@ <h1><f:translate key="installedExtensions" /></h1> <f:render partial="List/UploadForm" /> <form> - <div class="row row-cols-auto align-items-end justify-content-between g-3"> - <div class="col"> + <div class="form-row justify-content-between"> + <div class="form-group"> <div class="input-group"> <f:form.textfield name="Tx_Extensionmanager_extensionkey" placeholder="{f:translate(key:'extensionList.search')}" id="Tx_Extensionmanager_extensionkey" value="{search}" class="form-control extension-list-search" /> <button type="submit" class="btn btn-default"><core:icon identifier="actions-search" /></button> </div> </div> - <div class="col"> + <div class="form-group"> <div class="btn-group"> <f:link.action action="index" diff --git a/typo3/sysext/extensionmanager/Resources/Private/Templates/List/Ter.html b/typo3/sysext/extensionmanager/Resources/Private/Templates/List/Ter.html index c01999eb15eb..52071249dff4 100644 --- a/typo3/sysext/extensionmanager/Resources/Private/Templates/List/Ter.html +++ b/typo3/sysext/extensionmanager/Resources/Private/Templates/List/Ter.html @@ -19,8 +19,8 @@ <h1><f:translate key="getExtensions">Get Extensions</f:translate></h1> <f:render partial="List/UploadForm" /> - <div class="row row-cols-auto align-items-end justify-content-between g-3"> - <div class="col"> + <div class="form-row justify-content-between"> + <div class="form-group"> <f:form class="typo3-extensionmanager-searchTerForm" action="ter"> <div class="input-group"> <f:form.textfield name="search" value="{search}" class="form-control" placeholder="{f:translate(key:'extensionList.search')}" /> @@ -30,7 +30,7 @@ </div> </f:form> </div> - <div class="col"> + <div class="form-group"> <f:render partial="List/UpdateFromTer" /> </div> </div> diff --git a/typo3/sysext/filelist/Resources/Private/Templates/File/List.html b/typo3/sysext/filelist/Resources/Private/Templates/File/List.html index a3f867f86ea6..832765b853ff 100644 --- a/typo3/sysext/filelist/Resources/Private/Templates/File/List.html +++ b/typo3/sysext/filelist/Resources/Private/Templates/File/List.html @@ -43,8 +43,8 @@ <form method="post" name="fileListForm" action="{listUrl}"> <input type="hidden" name="cmd"/> <f:if condition="{searchTerm} || {totalItems}"> - <div class="row mb-3"> - <div class="col-6"> + <div class="form-row"> + <div class="form-group"> <div class="input-group"> <button class="btn btn-default" type="submit" name="search"> <core:icon identifier="actions-search" size="small" /> @@ -143,6 +143,7 @@ <f:if condition="{listHtml}"> <f:if condition="{showClipboardPanel}"> + <hr class="spacer"> <typo3-backend-clipboard-panel return-url="{listUrl}" table="_FILE"></typo3-backend-clipboard-panel> </f:if> </f:if> diff --git a/typo3/sysext/impexp/Resources/Private/Templates/Export.html b/typo3/sysext/impexp/Resources/Private/Templates/Export.html index 4b0c72550552..4f4f2ee1403d 100644 --- a/typo3/sysext/impexp/Resources/Private/Templates/Export.html +++ b/typo3/sysext/impexp/Resources/Private/Templates/Export.html @@ -5,8 +5,8 @@ > <f:layout name="Module" /> -<f:section name="Content"> +<f:section name="Before"> <f:be.pageRenderer includeJavaScriptModules="{ 0: '@typo3/backend/context-menu.js', @@ -14,15 +14,20 @@ 2: '@typo3/backend/element/immediate-action-element.js' }" /> - <form action="{f:be.uri(route:'tx_impexp_export')}" method="post" id="ImportExportController"> - <f:variable name="args" value="{0: 'web', 1: id}" /> - <typo3-immediate-action action="TYPO3.Backend.Storage.ModuleStateStorage.update" args="{args -> f:format.json() -> f:format.htmlspecialchars()}"></typo3-immediate-action> - <input type="hidden" name="id" value="{id}" /> + <f:variable name="args" value="{0: 'web', 1: id}" /> + <typo3-immediate-action + action="TYPO3.Backend.Storage.ModuleStateStorage.update" + args="{args -> f:format.json() -> f:format.htmlspecialchars()}" + ></typo3-immediate-action> +</f:section> - <h1> - <f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:title_export" /> - </h1> +<f:section name="Content"> + <h1> + <f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:title_export" /> + </h1> + <form action="{f:be.uri(route:'tx_impexp_export')}" method="post" id="ImportExportController"> + <input type="hidden" name="id" value="{id}" /> <ul class="nav nav-tabs" role="tablist"> <li role="presentation" class="nav-item"> <a class="nav-link text-capitalize active" href="#export-configuration" aria-controls="export-configuration" role="tab" data-bs-toggle="tab"> @@ -68,7 +73,6 @@ </div> </f:if> </div> - <f:render partial="Preview" arguments="{_all}" /> </form> diff --git a/typo3/sysext/impexp/Resources/Private/Templates/Import.html b/typo3/sysext/impexp/Resources/Private/Templates/Import.html index 7376e5a18d8a..b74b5684e463 100644 --- a/typo3/sysext/impexp/Resources/Private/Templates/Import.html +++ b/typo3/sysext/impexp/Resources/Private/Templates/Import.html @@ -5,8 +5,8 @@ > <f:layout name="Module" /> -<f:section name="Content"> +<f:section name="Before"> <f:be.pageRenderer includeJavaScriptModules="{ 0: '@typo3/backend/context-menu.js', @@ -14,15 +14,20 @@ 2: '@typo3/backend/element/immediate-action-element.js' }" /> - <form action="{f:be.uri(route:'tx_impexp_import')}" method="post" id="ImportExportController" enctype="multipart/form-data"> - <f:variable name="args" value="{0: 'web', 1: id}" /> - <typo3-immediate-action action="TYPO3.Backend.Storage.ModuleStateStorage.update" args="{args -> f:format.json() -> f:format.htmlspecialchars()}"></typo3-immediate-action> - <input type="hidden" name="id" value="{id}" /> + <f:variable name="args" value="{0: 'web', 1: id}" /> + <typo3-immediate-action + action="TYPO3.Backend.Storage.ModuleStateStorage.update" + args="{args -> f:format.json() -> f:format.htmlspecialchars()}" + ></typo3-immediate-action> +</f:section> - <h1> - <f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:title_import" /> - </h1> +<f:section name="Content"> + <h1> + <f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:title_import" /> + </h1> + <form action="{f:be.uri(route:'tx_impexp_import')}" method="post" id="ImportExportController" enctype="multipart/form-data"> + <input type="hidden" name="id" value="{id}" /> <ul class="nav nav-tabs" role="tablist"> <li role="presentation" class="nav-item"> <a class="nav-link text-capitalize active" href="#import-import" aria-controls="import-import" role="tab" data-bs-toggle="tab"> diff --git a/typo3/sysext/indexed_search/Resources/Private/Templates/Administration/Index.html b/typo3/sysext/indexed_search/Resources/Private/Templates/Administration/Index.html index fbf057a5b686..326d5b6e1744 100644 --- a/typo3/sysext/indexed_search/Resources/Private/Templates/Administration/Index.html +++ b/typo3/sysext/indexed_search/Resources/Private/Templates/Administration/Index.html @@ -11,7 +11,7 @@ <h2><f:translate key="administration.index.description" /></h2> <div class="row"> <div class="col-md-6"> - <h4><f:translate key="administration.statistics.header" /></h4> + <h3><f:translate key="administration.statistics.header" /></h3> <div class="table-fit"> <table class="table table-striped table-hover"> <thead> @@ -32,7 +32,7 @@ </div> </div> <div class="col-md-6"> - <h4><f:translate key="administration.statistics.headerTypes" /></h4> + <h3><f:translate key="administration.statistics.headerTypes" /></h3> <div class="table-fit"> <table class="table table-striped table-hover"> <thead> @@ -91,9 +91,9 @@ </f:section> <f:section name="statistic"> - <h4> + <h3> <f:translate key="administration.statistics.mostSearched.{title}" /> - </h4> + </h3> <f:if condition="{statistic}"> <f:then> <div class="table-fit"> diff --git a/typo3/sysext/indexed_search/Resources/Private/Templates/Administration/Statistic.html b/typo3/sysext/indexed_search/Resources/Private/Templates/Administration/Statistic.html index d113dfabdd27..3e9cf331617b 100644 --- a/typo3/sysext/indexed_search/Resources/Private/Templates/Administration/Statistic.html +++ b/typo3/sysext/indexed_search/Resources/Private/Templates/Administration/Statistic.html @@ -12,8 +12,8 @@ <f:if condition="{tree}"> <f:then> <f:form name="statistic" action="statistic" arguments="{id:pageUid}"> - <div class="row row-cols-auto align-items-center g-3 mb-3"> - <div class="col"> + <div class="form-row"> + <div class="form-group"> <label for="mode" class="form-label"> <f:translate key="LLL:EXT:indexed_search/Resources/Private/Language/locallang.xlf:administration.moduleFunctions.mode" /> </label> @@ -22,7 +22,7 @@ content:'{f:translate(key:\'administration.statistics.view.content\')}' }" value="{mode}" additionalAttributes="{data-global-event='change', data-action-submit: '$form'}" /> </div> - <div class="col"> + <div class="form-group"> <label for="depth" class="form-label"> <f:translate key="LLL:EXT:indexed_search/Resources/Private/Language/locallang.xlf:administration.moduleFunctions.depth" /> </label> diff --git a/typo3/sysext/indexed_search/Resources/Private/Templates/Administration/StatisticDetails.html b/typo3/sysext/indexed_search/Resources/Private/Templates/Administration/StatisticDetails.html index a03d5ad5baa4..81149d891569 100644 --- a/typo3/sysext/indexed_search/Resources/Private/Templates/Administration/StatisticDetails.html +++ b/typo3/sysext/indexed_search/Resources/Private/Templates/Administration/StatisticDetails.html @@ -31,22 +31,22 @@ <f:render section="wordlisting" arguments="{words:topFrequency,phash:phash,title:'topFrequency'}" /> <f:if condition="{debug}"> - <h4> + <h3> <f:translate key="administration.statistics.debug" /> - </h4> + </h3> <f:debug inline="1" title="">{debug}</f:debug> </f:if> <f:if condition="{lexer}"> - <h4> + <h3> <f:translate key="administration.statistics.lexer" /> - </h4> + </h3> <f:format.raw>{lexer}</f:format.raw> </f:if> <f:if condition="{metaphone}"> - <h4> + <h3> <f:translate key="administration.statistics.metaphone" /> - </h4> + </h3> <div class="table-fit"> <table class="table table-striped table-hover"> <thead> @@ -81,7 +81,7 @@ </div> </f:if> <f:if condition="{sections}"> - <h4><f:translate key="administration.statistics.sectionRecords" /></h4> + <h3><f:translate key="administration.statistics.sectionRecords" /></h3> <div class="table-fit"> <table class="table table-striped table-hover"> <thead> @@ -117,12 +117,12 @@ </f:section> <f:section name="wordlisting"> - <h4> + <h3> <f:translate key="administration.document.{title}" /> <f:if condition="{title}=='words'"> ({f:count(subject:words)}) </f:if> - </h4> + </h3> <f:if condition="{words}"> <f:form class="form" method="post" action="saveStopwordsKeywords" name="stopwordskeywords" arguments="{pageHash:phash}"> <f:form.hidden name="pageHash" value="{phash}" /> diff --git a/typo3/sysext/info/Resources/Private/Templates/PageInformation.html b/typo3/sysext/info/Resources/Private/Templates/PageInformation.html index 06bbd3332543..db24f00a9761 100644 --- a/typo3/sysext/info/Resources/Private/Templates/PageInformation.html +++ b/typo3/sysext/info/Resources/Private/Templates/PageInformation.html @@ -5,35 +5,40 @@ <f:layout name="Module"/> -<f:section name="Content"> - +<f:section name="Before"> <f:be.pageRenderer includeJavaScriptModules="{ 0: '@typo3/backend/context-menu.js', 1: '@typo3/backend/element/immediate-action-element.js' }" /> + <f:if condition="{accessContent}"> + <f:variable name="args" value="{0: 'web', 1: id}"/> + <typo3-immediate-action + action="TYPO3.Backend.Storage.ModuleStateStorage.update" + args="{args -> f:format.json() -> f:format.htmlspecialchars()}" + ></typo3-immediate-action> + </f:if> +</f:section> + +<f:section name="Content"> <f:if condition="{accessContent}"> <f:then> - - <f:variable name="args" value="{0: 'web', 1: id}"/> - <typo3-immediate-action action="TYPO3.Backend.Storage.ModuleStateStorage.update" - args="{args -> f:format.json() -> f:format.htmlspecialchars()}"></typo3-immediate-action> <h1> <f:translate key="LLL:EXT:info/Resources/Private/Language/locallang_webinfo.xlf:page_title"/> </h1> <f:if condition="{content}"> <form action="{f:be.uri(route: 'web_info_overview', parameters: '{id: pageUid}')}" method="post"> - <div class="row row-cols-auto mb-3 g-3 align-items-center"> - <div class="col"> + <div class="form-row"> + <div class="form-group"> <label class="form-label" for="depth"> <f:translate key="LLL:EXT:info/Resources/Private/Language/locallang_webinfo.xlf:moduleFunctions.depth"/> </label> <f:render partial="DropdownMenu" arguments="{name: 'depth', id: 'depth', options: depthDropdownOptions, currentValue: depthDropdownCurrentValue}"/> </div> - <div class="col"> + <div class="form-group"> <label class="form-label" for="pages"> <f:translate key="LLL:EXT:info/Resources/Private/Language/locallang_webinfo.xlf:moduleFunctions.type"/> </label> diff --git a/typo3/sysext/info/Resources/Private/Templates/TranslationStatus.html b/typo3/sysext/info/Resources/Private/Templates/TranslationStatus.html index 49203018cf59..c172fc743f3a 100644 --- a/typo3/sysext/info/Resources/Private/Templates/TranslationStatus.html +++ b/typo3/sysext/info/Resources/Private/Templates/TranslationStatus.html @@ -5,8 +5,7 @@ <f:layout name="Module"/> -<f:section name="Content"> - +<f:section name="Before"> <f:be.pageRenderer includeJavaScriptModules="{ 0: '@typo3/backend/context-menu.js', @@ -14,29 +13,39 @@ 2: '@typo3/info/translation-status.js' }" /> + <f:if condition="{accessContent}"> + <f:variable name="args" value="{0: 'web', 1: id}" /> + <typo3-immediate-action + action="TYPO3.Backend.Storage.ModuleStateStorage.update" + args="{args -> f:format.json() -> f:format.htmlspecialchars()}" + ></typo3-immediate-action> + </f:if> +</f:section> + +<f:section name="Content"> <f:if condition="{accessContent}"> <f:then> - <f:variable name="args" value="{0: 'web', 1: id}" /> - <typo3-immediate-action action="TYPO3.Backend.Storage.ModuleStateStorage.update" args="{args -> f:format.json() -> f:format.htmlspecialchars()}"></typo3-immediate-action> <h1><f:translate key="LLL:EXT:info/Resources/Private/Language/locallang_webinfo.xlf:lang_title" /></h1> <f:if condition="{content}"> - <form action="{f:be.uri(route: 'web_info_translations', parameters: '{id: pageUid}')}" method="post" id="InfoModuleController" name="webinfoForm"><div class="row row-cols-auto mb-3 g-3 align-items-center"> - <div class="col"> - <label class="form-label" for="depth"> - <f:translate key="LLL:EXT:info/Resources/Private/Language/locallang_webinfo.xlf:moduleFunctions.depth" /> - </label> - <f:render partial="DropdownMenu" arguments="{name: 'depth', id: 'depth', options: depthDropdownOptions, currentValue: depthDropdownCurrentValue}"/> - </div> - <f:if condition="{displayLangDropdown}"> - <div class="col"> - <label class="form-label" for="lang"> - <f:translate key="LLL:EXT:info/Resources/Private/Language/locallang_webinfo.xlf:moduleFunctions.lang" /> + <form action="{f:be.uri(route: 'web_info_translations', parameters: '{id: pageUid}')}" method="post" id="InfoModuleController" name="webinfoForm"> + <div class="form-row"> + <div class="form-group"> + <label class="form-label" for="depth"> + <f:translate key="LLL:EXT:info/Resources/Private/Language/locallang_webinfo.xlf:moduleFunctions.depth" /> </label> - <f:render partial="DropdownMenu" arguments="{name: 'lang', id: 'lang', options: langDropdownOptions, currentValue: langDropdownCurrentValue}"/> + <f:render partial="DropdownMenu" arguments="{name: 'depth', id: 'depth', options: depthDropdownOptions, currentValue: depthDropdownCurrentValue}"/> </div> - </f:if> - </div><f:format.raw>{content}</f:format.raw> + <f:if condition="{displayLangDropdown}"> + <div class="form-group"> + <label class="form-label" for="lang"> + <f:translate key="LLL:EXT:info/Resources/Private/Language/locallang_webinfo.xlf:moduleFunctions.lang" /> + </label> + <f:render partial="DropdownMenu" arguments="{name: 'lang', id: 'lang', options: langDropdownOptions, currentValue: langDropdownCurrentValue}"/> + </div> + </f:if> + </div> + <f:format.raw>{content}</f:format.raw> </form> </f:if> </f:then> diff --git a/typo3/sysext/install/Resources/Private/Templates/Environment/ImageProcessing.html b/typo3/sysext/install/Resources/Private/Templates/Environment/ImageProcessing.html index ac20d87517e1..e2b96e4295d0 100644 --- a/typo3/sysext/install/Resources/Private/Templates/Environment/ImageProcessing.html +++ b/typo3/sysext/install/Resources/Private/Templates/Environment/ImageProcessing.html @@ -1,36 +1,12 @@ <html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true"> -<div style="display:none;"> - <div class="t3js-imageProcessing-twinImage-template"> - <div class="t3-install-displaytwinimageimages t3js-imageProcessing-images" style="display:none;"> - <div class="row"> - <div class="col-12 col-md-6"> - <h4>Reference</h4> - <div class="bg-transparent-emulation"> - <img class="reference"/> - </div> - </div> - <div class="col-12 col-md-6"> - <h4>Your system</h4> - <div class="bg-transparent-emulation"> - <img class="result"/> - </div> - </div> - </div> - </div> - <div class="t3-install-displaytwinimagetextarea t3js-imageProcessing-command" style="display:none;"> - <pre class="mt-2"><code class="language-bash t3js-imageProcessing-command-text"></code></pre> - </div> - </div> -</div> - -<h3>True type font tests</h3> +<h2>True type font tests</h2> <f:be.infobox title="FreeType2 hint" state="-1"> <p>If the two images below do not look the same, please check your FreeType 2 module.</p> </f:be.infobox> <div class="t3js-imageProcessing-twinContainer" data-test="imageProcessingTrueType"></div> -<h3 class="mt-4">Convert image formats to jpg</h3> +<h2>Convert image formats to jpg</h2> <p> This verifies that your ImageMagick installation is able to read the default formats <code>jpg</code>, <code>gif</code>, <code>png</code>, <code>tif</code>, <code>pdf</code> and @@ -45,84 +21,84 @@ </p> </f:be.infobox> -<h4 class="mt-4">Read jpg</h4> +<h3>Read jpg</h3> <div class="t3js-imageProcessing-twinContainer" data-test="imageProcessingReadJpg"></div> -<h4 class="mt-4">Read gif</h4> +<h3>Read gif</h3> <div class="t3js-imageProcessing-twinContainer" data-test="imageProcessingReadGif"></div> -<h4 class="mt-4">Read png</h4> +<h3>Read png</h3> <div class="t3js-imageProcessing-twinContainer" data-test="imageProcessingReadPng"></div> -<h4 class="mt-4">Read tif</h4> +<h3>Read tif</h3> <div class="t3js-imageProcessing-twinContainer" data-test="imageProcessingReadTif"></div> -<h4 class="mt-4">Read pdf</h4> +<h3>Read pdf</h3> <div class="t3js-imageProcessing-twinContainer" data-test="imageProcessingReadPdf"></div> -<h4 class="mt-4">Read ai</h4> +<h3>Read ai</h3> <div class="t3js-imageProcessing-twinContainer" data-test="imageProcessingReadAi"></div> -<h3 class="mt-4">Writing gif, png, webp</h3> +<h2>Writing gif, png, webp</h2> <p> This verifies that ImageMagick is able to write GIF and PNG and WEBP files. The GIF-file is attempted compressed by the <code>\TYPO3\CMS\Core\Imaging\GraphicalFunctions::gifCompress()</code> function. </p> -<h4 class="mt-4">Write gif</h4> +<h3>Write gif</h3> <div class="t3js-imageProcessing-twinContainer" data-test="imageProcessingWriteGif"></div> -<h4 class="mt-4">Write png</h4> +<h3>Write png</h3> <div class="t3js-imageProcessing-twinContainer" data-test="imageProcessingWritePng"></div> -<h4 class="mt-4">Write webp</h4> +<h3>Write webp</h3> <div class="t3js-imageProcessing-twinContainer" data-test="imageProcessingWriteWebp"></div> -<h3 class="mt-4">Scaling images</h3> +<h2>Scaling images</h2> <p> This shows how ImageMagick reacts when scaling transparent GIF and PNG files. </p> -<h4 class="mt-4">gif to gif</h4> +<h3>gif to gif</h3> <div class="t3js-imageProcessing-twinContainer" data-test="imageProcessingGifToGif"></div> -<h4 class="mt-4">png to png</h4> +<h3>png to png</h3> <div class="t3js-imageProcessing-twinContainer" data-test="imageProcessingPngToPng"></div> -<h4 class="mt-4">gif to jpg</h4> +<h3>gif to jpg</h3> <div class="t3js-imageProcessing-twinContainer" data-test="imageProcessingGifToJpg"></div> -<h4 class="mt-4">jpg to webp</h4> +<h3>jpg to webp</h3> <div class="t3js-imageProcessing-twinContainer" data-test="imageProcessingJpgToWebp"></div> -<h3 class="mt-4">Combining images</h3> +<h2>Combining images</h2> <p> This verifies that the ImageMagick tools, <code>combine</code>, <code>composite</code>, are able to combine two images through a grayscale mask. </p> -<h4 class="mt-4">Combine using a GIF mask with only black and white</h4> +<h3>Combine using a GIF mask with only black and white</h3> <div class="t3js-imageProcessing-twinContainer" data-test="imageProcessingCombineGifMask"></div> -<h4 class="mt-4">Combine using a JPG mask with graylevels</h4> +<h3>Combine using a JPG mask with graylevels</h3> <div class="t3js-imageProcessing-twinContainer" data-test="imageProcessingCombineJpgMask"></div> -<h3 class="mt-4">GDlib</h3> +<h2>GDlib</h2> <p> This verifies that the GDLib installation works properly. </p> -<h4 class="mt-4">Create simple image</h4> +<h3>Create simple image</h3> <div class="t3js-imageProcessing-twinContainer" data-test="imageProcessingGdlibSimple"></div> -<h4 class="mt-4">Create image from file</h4> +<h3>Create image from file</h3> <div class="t3js-imageProcessing-twinContainer" data-test="imageProcessingGdlibFromFile"></div> -<h4 class="mt-4">Render text with TrueType font</h4> +<h3>Render text with TrueType font</h3> <div class="t3js-imageProcessing-twinContainer" data-test="imageProcessingGdlibRenderText"></div> -<h4 class="mt-4">Render text with TrueType font using 'niceText' option</h4> +<h3>Render text with TrueType font using 'niceText' option</h3> <f:be.infobox title="Note on 'niceText'" state="-1"> <p> 'niceText' is a concept that tries to improve the antialiasing of the rendered type by actually @@ -132,7 +108,7 @@ </f:be.infobox> <div class="t3js-imageProcessing-twinContainer" data-test="imageProcessingGdlibNiceText"></div> -<h4 class="mt-4">Render 'niceText' with a shadow under</h4> +<h3>Render 'niceText' with a shadow under</h3> <f:be.infobox title="Note on 'shadow'" state="-1"> <p> This test makes sense only if the above test had a correct output. But if so, you may not see @@ -142,7 +118,7 @@ </f:be.infobox> <div class="t3js-imageProcessing-twinContainer" data-test="imageProcessingGdlibNiceTextShadow"></div> -<div class="panel-group mt-4" id="accordion" role="tablist" aria-multiselectable="true"> +<div class="panel-group mb-0" id="accordion" role="tablist" aria-multiselectable="true"> <div class="panel panel-default"> <div class="panel-heading" role="tab" id="headingConfiguration"> <h4 class="panel-title"> @@ -150,11 +126,10 @@ <span class="caret"></span> Current configuration </a> - </h4> + </h3> </div> <div id="collapseConfiguration" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingConfiguration"> - <div class="panel-body"> - + <div class="table-fit"> <table class="table table-striped"> <tr> <td>{imageProcessingProcessor} enabled:</td> @@ -200,11 +175,11 @@ <span class="caret"></span> Verify test results </a> - </h4> + </h3> </div> <div id="collapseVerify" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingVerify"> <div class="panel-body"> - <h4>Verify test results</h4> + <h3>Verify test results</h3> <p> This page performs image processing and displays the result. It's a thorough check that everything you've configured is working correctly. @@ -229,7 +204,7 @@ <span class="caret"></span> About image handling </a> - </h4> + </h3> </div> <div id="collapseAbout" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingAbout"> <div class="panel-body"> @@ -288,7 +263,7 @@ <span class="caret"></span> About test images </a> - </h4> + </h3> </div> <div id="collapseTestImages" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingTestImages"> <div class="panel-body"> @@ -302,4 +277,28 @@ </div> </div> +<div style="display:none;"> + <div class="t3js-imageProcessing-twinImage-template"> + <div class="t3-install-displaytwinimageimages t3js-imageProcessing-images" style="display:none;"> + <div class="row"> + <div class="col-12 col-md-6"> + <h3>Reference</h3> + <div class="bg-transparent-emulation"> + <img class="reference"/> + </div> + </div> + <div class="col-12 col-md-6"> + <h3>Your system</h3> + <div class="bg-transparent-emulation"> + <img class="result"/> + </div> + </div> + </div> + </div> + <div class="t3-install-displaytwinimagetextarea t3js-imageProcessing-command" style="display:none;"> + <pre class="language-bash"><code class="language-bash t3js-imageProcessing-command-text"></code></pre> + </div> + </div> +</div> + </html> diff --git a/typo3/sysext/install/Resources/Public/JavaScript/renderable/clearable.js b/typo3/sysext/install/Resources/Public/JavaScript/renderable/clearable.js index b15486ad91bb..e90caeef460f 100644 --- a/typo3/sysext/install/Resources/Public/JavaScript/renderable/clearable.js +++ b/typo3/sysext/install/Resources/Public/JavaScript/renderable/clearable.js @@ -10,4 +10,4 @@ * * The TYPO3 project - inspiring people to share! */ -class Clearable{constructor(){"function"!=typeof HTMLInputElement.prototype.clearable&&this.registerClearable()}static createCloseButton(){const e=document.createElement("button");return e.type="button",e.tabIndex=-1,e.innerHTML='<span class="t3js-icon icon icon-size-small icon-state-default icon-actions-close" data-identifier="actions-close">\n <span class="icon-markup">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">\n <path\n d="M11.9 5.5L9.4 8l2.5 2.5c.2.2.2.5 0\n .7l-.7.7c-.2.2-.5.2-.7 0L8 9.4l-2.5 2.5c-.2.2-.5.2-.7\n 0l-.7-.7c-.2-.2-.2-.5 0-.7L6.6 8 4.1 5.5c-.2-.2-.2-.5\n 0-.7l.7-.7c.2-.2.5-.2.7 0L8 6.6l2.5-2.5c.2-.2.5-.2.7\n 0l.7.7c.2.2.2.5 0 .7z"\n class="icon-color"/>\n </svg>\n </span>\n </span>',e.style.visibility="hidden",e.classList.add("close"),e}registerClearable(){HTMLInputElement.prototype.clearable=function(e={}){if(this.dataset.clearable)return;if("object"!=typeof e)throw new Error("Passed options must be an object, "+typeof e+" given");const t=document.createElement("div");t.classList.add("form-control-clearable","form-control"),this.parentNode.insertBefore(t,this),t.appendChild(this);const n=Clearable.createCloseButton(),s=()=>{n.style.visibility=0===this.value.length?"hidden":"visible"};n.addEventListener("click",(t=>{t.preventDefault(),this.value="","function"==typeof e.onClear&&e.onClear(this),this.dispatchEvent(new Event("change",{bubbles:!0,cancelable:!0})),s()})),t.appendChild(n),this.addEventListener("focus",s),this.addEventListener("keyup",s),s(),this.dataset.clearable="true"}}}export default new Clearable; \ No newline at end of file +class Clearable{constructor(){"function"!=typeof HTMLInputElement.prototype.clearable&&this.registerClearable()}static createCloseButton(){const e=document.createElement("button");return e.type="button",e.tabIndex=-1,e.innerHTML='<span class="t3js-icon icon icon-size-small icon-state-default icon-actions-close" data-identifier="actions-close">\n <span class="icon-markup">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">\n <path\n d="M11.9 5.5L9.4 8l2.5 2.5c.2.2.2.5 0\n .7l-.7.7c-.2.2-.5.2-.7 0L8 9.4l-2.5 2.5c-.2.2-.5.2-.7\n 0l-.7-.7c-.2-.2-.2-.5 0-.7L6.6 8 4.1 5.5c-.2-.2-.2-.5\n 0-.7l.7-.7c.2-.2.5-.2.7 0L8 6.6l2.5-2.5c.2-.2.5-.2.7\n 0l.7.7c.2.2.2.5 0 .7z"\n class="icon-color"/>\n </svg>\n </span>\n </span>',e.style.visibility="hidden",e.classList.add("close"),e}registerClearable(){HTMLInputElement.prototype.clearable=function(e={}){if(this.dataset.clearable)return;if("object"!=typeof e)throw new Error("Passed options must be an object, "+typeof e+" given");this.classList.add("form-control-clearable");const t=document.createElement("div");t.classList.add("form-control-clearable-wrapper"),this.parentNode.insertBefore(t,this),t.appendChild(this);const n=Clearable.createCloseButton(),a=()=>{n.style.visibility=0===this.value.length?"hidden":"visible"};n.addEventListener("click",(t=>{t.preventDefault(),this.value="","function"==typeof e.onClear&&e.onClear(this),this.dispatchEvent(new Event("change",{bubbles:!0,cancelable:!0})),a()})),t.appendChild(n),this.addEventListener("focus",a),this.addEventListener("keyup",a),a(),this.dataset.clearable="true"}}}export default new Clearable; \ No newline at end of file diff --git a/typo3/sysext/linkvalidator/Resources/Private/Partials/LevelSelector.html b/typo3/sysext/linkvalidator/Resources/Private/Partials/LevelSelector.html index c9b1a9516797..4f38a44004b3 100644 --- a/typo3/sysext/linkvalidator/Resources/Private/Partials/LevelSelector.html +++ b/typo3/sysext/linkvalidator/Resources/Private/Partials/LevelSelector.html @@ -3,15 +3,13 @@ data-namespace-typo3-fluid="true" > -<div> - <select name="{prefix}_search_levels" class="form-select"> - <option value="0"{f:if(condition: '{selectedLevel} == 0', then: 'selected')}><f:translate key="LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_0" /></option> - <option value="1"{f:if(condition: '{selectedLevel} == 1', then: 'selected')}><f:translate key="LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_1" /></option> - <option value="2"{f:if(condition: '{selectedLevel} == 2', then: 'selected')}><f:translate key="LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_2" /></option> - <option value="3"{f:if(condition: '{selectedLevel} == 3', then: 'selected')}><f:translate key="LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_3" /></option> - <option value="4"{f:if(condition: '{selectedLevel} == 4', then: 'selected')}><f:translate key="LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_4" /></option> - <option value="999"{f:if(condition: '{selectedLevel} == 999', then: 'selected')}><f:translate key="LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_infi" /></option> - </select> -</div> +<select name="{prefix}_search_levels" class="form-select"> + <option value="0"{f:if(condition: '{selectedLevel} == 0', then: 'selected')}><f:translate key="LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_0" /></option> + <option value="1"{f:if(condition: '{selectedLevel} == 1', then: 'selected')}><f:translate key="LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_1" /></option> + <option value="2"{f:if(condition: '{selectedLevel} == 2', then: 'selected')}><f:translate key="LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_2" /></option> + <option value="3"{f:if(condition: '{selectedLevel} == 3', then: 'selected')}><f:translate key="LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_3" /></option> + <option value="4"{f:if(condition: '{selectedLevel} == 4', then: 'selected')}><f:translate key="LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_4" /></option> + <option value="999"{f:if(condition: '{selectedLevel} == 999', then: 'selected')}><f:translate key="LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_infi" /></option> +</select> </html> diff --git a/typo3/sysext/linkvalidator/Resources/Private/Templates/Backend/CheckLinks.html b/typo3/sysext/linkvalidator/Resources/Private/Templates/Backend/CheckLinks.html index 4674a77e1de7..d7f8eff2c167 100644 --- a/typo3/sysext/linkvalidator/Resources/Private/Templates/Backend/CheckLinks.html +++ b/typo3/sysext/linkvalidator/Resources/Private/Templates/Backend/CheckLinks.html @@ -16,12 +16,16 @@ </f:if> <div class="row row-cols-auto align-items-start t3js-linkvalidator-settings"> <div class="col"> - <h4><f:translate key="LLL:EXT:linkvalidator/Resources/Private/Language/Module/locallang.xlf:checklinks.statistics.header" /></h4> - <f:render partial="CheckOptions" arguments="{_all}" /> + <div class="form-group"> + <label class="form-label"><f:translate key="LLL:EXT:linkvalidator/Resources/Private/Language/Module/locallang.xlf:checklinks.statistics.header" /></label> + <f:render partial="CheckOptions" arguments="{_all}" /> + </div> </div> - <div class="col mb-3"> - <h4><f:translate key="LLL:EXT:linkvalidator/Resources/Private/Language/Module/locallang.xlf:checklinks.func.title" /></h4> - <f:render partial="LevelSelector" arguments="{_all}" /> + <div class="col"> + <div class="form-group"> + <label class="form-label"><f:translate key="LLL:EXT:linkvalidator/Resources/Private/Language/Module/locallang.xlf:checklinks.func.title" /></label> + <f:render partial="LevelSelector" arguments="{_all}" /> + </div> </div> <div class="col-12"> <input diff --git a/typo3/sysext/linkvalidator/Resources/Private/Templates/Backend/Report.html b/typo3/sysext/linkvalidator/Resources/Private/Templates/Backend/Report.html index d796509c7bf3..fc1f7d767fc3 100644 --- a/typo3/sysext/linkvalidator/Resources/Private/Templates/Backend/Report.html +++ b/typo3/sysext/linkvalidator/Resources/Private/Templates/Backend/Report.html @@ -14,14 +14,18 @@ <f:if condition="{title}"> <h1>{title}</h1> </f:if> - <div class="row row-cols-auto align-items-start t3js-linkvalidator-settings mb-4"> + <div class="row row-cols-auto align-items-start t3js-linkvalidator-settings"> <div class="col"> - <h4><f:translate key="LLL:EXT:linkvalidator/Resources/Private/Language/Module/locallang.xlf:report.statistics.header" /></h4> - <f:render partial="CheckOptions" arguments="{_all}" /> + <div class="form-group"> + <label class="form-label"><f:translate key="LLL:EXT:linkvalidator/Resources/Private/Language/Module/locallang.xlf:report.statistics.header" /></label> + <f:render partial="CheckOptions" arguments="{_all}" /> + </div> </div> - <div class="col mb-3"> - <h4><f:translate key="LLL:EXT:linkvalidator/Resources/Private/Language/Module/locallang.xlf:report.func.title" /></h4> - <f:render partial="LevelSelector" arguments="{_all}" /> + <div class="col"> + <div class="form-group"> + <label class="form-label"><f:translate key="LLL:EXT:linkvalidator/Resources/Private/Language/Module/locallang.xlf:report.func.title" /></label> + <f:render partial="LevelSelector" arguments="{_all}" /> + </div> </div> <div class="col-12"> <input @@ -35,7 +39,7 @@ </div> </div> - <h3><f:translate key="LLL:EXT:linkvalidator/Resources/Private/Language/Module/locallang.xlf:list.header" /></h3> + <h2><f:translate key="LLL:EXT:linkvalidator/Resources/Private/Language/Module/locallang.xlf:list.header" /></h2> <f:if condition="{brokenLinks -> f:count()}"> <f:then> <div class="table-fit"> diff --git a/typo3/sysext/lowlevel/Classes/Controller/DatabaseIntegrityController.php b/typo3/sysext/lowlevel/Classes/Controller/DatabaseIntegrityController.php index 83ae6604854b..505e684b2e72 100644 --- a/typo3/sysext/lowlevel/Classes/Controller/DatabaseIntegrityController.php +++ b/typo3/sysext/lowlevel/Classes/Controller/DatabaseIntegrityController.php @@ -409,6 +409,7 @@ class DatabaseIntegrityController 'binaryPath' => ExtensionManagementUtility::extPath('core', 'bin/typo3'), 'referenceIndexResult' => $referenceIndexResult, ]); + return $view->renderResponse('ReferenceIndex'); } @@ -421,18 +422,21 @@ class DatabaseIntegrityController $this->showFieldAndTableNames = $this->getBackendUserAuthentication()->shallDisplayDebugInformation(); $searchMode = $this->MOD_SETTINGS['search']; $this->setFormName('queryform'); - $submenu = '<div class="row row-cols-auto align-items-end g-3 mb-4">'; - $submenu .= '<div class="col">' . self::getDropdownMenu(0, 'SET[search]', $searchMode, $this->MOD_MENU['search'], $request) . '</div>'; + $submenu = ''; + $submenu .= '<div class="form-row">'; + $submenu .= '<div class="form-group">' . self::getDropdownMenu(0, 'SET[search]', $searchMode, $this->MOD_MENU['search'], $request) . '</div>'; if ($this->MOD_SETTINGS['search'] === 'query') { - $submenu .= '<div class="col">' . self::getDropdownMenu(0, 'SET[search_query_makeQuery]', $this->MOD_SETTINGS['search_query_makeQuery'], $this->MOD_MENU['search_query_makeQuery'], $request) . '</div>'; + $submenu .= '<div class="form-group">' . self::getDropdownMenu(0, 'SET[search_query_makeQuery]', $this->MOD_SETTINGS['search_query_makeQuery'], $this->MOD_MENU['search_query_makeQuery'], $request) . '</div>'; } $submenu .= '</div>'; if ($this->MOD_SETTINGS['search'] === 'query') { + $submenu .= '<div class="form-group">'; $submenu .= '<div class="form-check">' . self::getFuncCheck(0, 'SET[search_query_smallparts]', $this->MOD_SETTINGS['search_query_smallparts'] ?? '', $request, '', '', 'id="checkSearch_query_smallparts"') . '<label class="form-check-label" for="checkSearch_query_smallparts">' . $lang->sL('LLL:EXT:lowlevel/Resources/Private/Language/locallang.xlf:showSQL') . '</label></div>'; $submenu .= '<div class="form-check">' . self::getFuncCheck(0, 'SET[search_result_labels]', $this->MOD_SETTINGS['search_result_labels'] ?? '', $request, '', '', 'id="checkSearch_result_labels"') . '<label class="form-check-label" for="checkSearch_result_labels">' . $lang->sL('LLL:EXT:lowlevel/Resources/Private/Language/locallang.xlf:useFormattedStrings') . '</label></div>'; $submenu .= '<div class="form-check">' . self::getFuncCheck(0, 'SET[labels_noprefix]', $this->MOD_SETTINGS['labels_noprefix'] ?? '', $request, '', '', 'id="checkLabels_noprefix"') . '<label class="form-check-label" for="checkLabels_noprefix">' . $lang->sL('LLL:EXT:lowlevel/Resources/Private/Language/locallang.xlf:dontUseOrigValues') . '</label></div>'; $submenu .= '<div class="form-check">' . self::getFuncCheck(0, 'SET[options_sortlabel]', $this->MOD_SETTINGS['options_sortlabel'] ?? '', $request, '', '', 'id="checkOptions_sortlabel"') . '<label class="form-check-label" for="checkOptions_sortlabel">' . $lang->sL('LLL:EXT:lowlevel/Resources/Private/Language/locallang.xlf:sortOptions') . '</label></div>'; $submenu .= '<div class="form-check">' . self::getFuncCheck(0, 'SET[show_deleted]', $this->MOD_SETTINGS['show_deleted'] ?? 0, $request, '', '', 'id="checkShow_deleted"') . '<label class="form-check-label" for="checkShow_deleted">' . $lang->sL('LLL:EXT:lowlevel/Resources/Private/Language/locallang.xlf:showDeleted') . '</label></div>'; + $submenu .= '</div>'; } $view->assign('submenu', $submenu); $view->assign('searchMode', $searchMode); @@ -445,6 +449,7 @@ class DatabaseIntegrityController $view->assign('searchOptions', $this->form()); $view->assign('results', $this->search($request)); } + return $view->renderResponse('CustomSearch'); } @@ -460,8 +465,8 @@ class DatabaseIntegrityController $msg = $this->procesStoreControl($request); $userTsConfig = $this->getBackendUserAuthentication()->getTSConfig(); if (!($userTsConfig['mod.']['dbint.']['disableStoreControl'] ?? false)) { - $output .= '<h2>Load/Save Query</h2>'; - $output .= '<div>' . $this->makeStoreControl() . '</div>'; + $output .= '<h2 class="headline-spaced">Load/Save Query</h2>'; + $output .= $this->makeStoreControl(); $output .= $msg; } // Query Maker: @@ -469,8 +474,8 @@ class DatabaseIntegrityController if ($this->formName) { $this->setFormName($this->formName); } - $tmpCode = $this->makeSelectorTable($this->MOD_SETTINGS, $request); - $output .= '<div id="query"></div><h2>Make query</h2><div>' . $tmpCode . '</div>'; + $output .= '<h2>Make query</h2>'; + $output .= $this->makeSelectorTable($this->MOD_SETTINGS, $request); $mQ = $this->MOD_SETTINGS['search_query_makeQuery'] ?? ''; // Make form elements: if ($this->table && is_array($GLOBALS['TCA'][$this->table])) { @@ -505,22 +510,38 @@ class DatabaseIntegrityController $dataRows = $connection->executeQuery($selectQueryString)->fetchAllAssociative(); } if (!($userTsConfig['mod.']['dbint.']['disableShowSQLQuery'] ?? false)) { - $output .= '<h2>SQL query</h2><div><code>' . htmlspecialchars($fullQueryString) . '</code></div>'; + $output .= '<h2>SQL query</h2>'; + $output .= '<pre class="language-sql">'; + $output .= '<code class="language-sql">'; + $output .= htmlspecialchars($fullQueryString); + $output .= '</code>'; + $output .= '</pre>'; } $cPR = $this->getQueryResultCode($mQ, $dataRows, $this->table, $request); - $output .= '<h2>' . ($cPR['header'] ?? '') . '</h2><div>' . $cPR['content'] . '</div>'; + if ($cPR['header'] ?? null) { + $output .= '<h2>' . $cPR['header'] . '</h2>'; + } + if ($cPR['content'] ?? null) { + $output .= $cPR['content']; + } } catch (DBALException $e) { if (!($userTsConfig['mod.']['dbint.']['disableShowSQLQuery'] ?? false)) { - $output .= '<h2>SQL query</h2><div><code>' . htmlspecialchars($fullQueryString) . '</code></div>'; + $output .= '<h2>SQL query</h2>'; + $output .= '<pre class="language-sql">'; + $output .= '<code class="language-sql">'; + $output .= htmlspecialchars($fullQueryString); + $output .= '</code>'; + $output .= '</pre>'; } - $out = '<p><strong>Error: <span class="text-danger">' - . htmlspecialchars($e->getMessage()) - . '</span></strong></p>'; - $output .= '<h2>SQL error</h2><div>' . $out . '</div>'; + $output .= '<h2>SQL error</h2>'; + $output .= '<div class="alert alert-danger">'; + $output .= '<p class="alert-message"><strong>Error:</strong> ' . htmlspecialchars($e->getMessage()) . '</p>'; + $output .= '</div>'; } } } - return '<div class="database-query-builder">' . $output . '</div>'; + + return $output; } protected function getSelectQuery(string $qString = ''): string @@ -646,6 +667,7 @@ class DatabaseIntegrityController } } } + return $theList; } @@ -660,7 +682,7 @@ class DatabaseIntegrityController switch ($type) { case 'count': $cPR['header'] = 'Count'; - $cPR['content'] = '<br><strong>' . (int)$dataRows[0] . '</strong> records selected.'; + $cPR['content'] = '<p><strong>' . (int)$dataRows[0] . '</strong> records selected.</p>'; break; case 'all': $rowArr = []; @@ -675,9 +697,11 @@ class DatabaseIntegrityController } if (!empty($rowArr)) { $cPR['header'] = 'Result'; - $out .= '<div class="table-fit"><table class="table table-striped table-hover">' - . $this->resultRowTitles((array)$dataRow, $GLOBALS['TCA'][$table]) . implode(LF, $rowArr) - . '</table></div>'; + $out .= '<div class="table-fit">'; + $out .= '<table class="table table-striped table-hover">'; + $out .= $this->resultRowTitles((array)$dataRow, $GLOBALS['TCA'][$table]) . implode(LF, $rowArr); + $out .= '</table>'; + $out .= '</div>'; } else { $this->renderNoResultsFoundMessage(); } @@ -696,12 +720,16 @@ class DatabaseIntegrityController } if (!empty($rowArr)) { $cPR['header'] = 'Result'; - $out .= '<textarea name="whatever" rows="20" class="font-monospace" style="width:100%">' - . htmlspecialchars(implode(LF, $rowArr)) - . '</textarea>'; + $out .= '<div class="form-group">'; + $out .= '<textarea class="form-control" name="whatever" rows="20" class="font-monospace" style="width:100%">'; + $out .= htmlspecialchars(implode(LF, $rowArr)); + $out .= '</textarea>'; + $out .= '</div>'; if (!$this->noDownloadB) { - $out .= '<br><input class="btn btn-default" type="submit" name="download_file" ' - . 'value="Click to download file">'; + $out .= '<button class="btn btn-default" type="submit" name="download_file" value="Click to download file">'; + $out .= $this->iconFactory->getIcon('actions-file-csv-download', Icon::SIZE_SMALL)->render(); + $out .= ' Click to download file'; + $out .= '</button>'; } // Downloads file: // @todo: args. routing anyone? @@ -721,11 +749,12 @@ class DatabaseIntegrityController case 'explain': default: foreach ($dataRows as $dataRow) { - $out .= '<br />' . DebugUtility::viewArray($dataRow); + $out .= DebugUtility::viewArray($dataRow); } $cPR['header'] = 'Explain SQL query'; $cPR['content'] = $out; } + return $cPR; } @@ -737,6 +766,7 @@ class DatabaseIntegrityController $valueArray[$key] = $this->getProcessedValueExtra($table, $key, (string)$val, $conf, ';'); } } + return CsvUtility::csvValues($valueArray, $delim, $quote); } @@ -768,6 +798,7 @@ class DatabaseIntegrityController $tableHeader[] = '<th></th>'; // Close header row $tableHeader[] = '</tr></thead>'; + return implode(LF, $tableHeader); } @@ -789,7 +820,7 @@ class DatabaseIntegrityController $out .= '<td>' . $fVnew . '</td>'; } } - $out .= '<td>'; + $out .= '<td class="col-control">'; $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class); if (!($row['deleted'] ?? false)) { @@ -804,7 +835,8 @@ class DatabaseIntegrityController . HttpUtility::buildQueryString(['SET' => $request->getParsedBody()['SET'] ?? []], '&'), ]); $out .= '<a class="btn btn-default" href="' . htmlspecialchars($url) . '">' - . $this->iconFactory->getIcon('actions-open', Icon::SIZE_SMALL)->render() . '</a>'; + . $this->iconFactory->getIcon('actions-open', Icon::SIZE_SMALL)->render() + . '</a>'; $out .= '</div><div class="btn-group" role="group">'; $out .= sprintf( '<a class="btn btn-default" href="#" data-dispatch-action="%s" data-dispatch-args-list="%s">%s</a>', @@ -835,6 +867,7 @@ class DatabaseIntegrityController } } $out .= '</td></tr>'; + return $out; } @@ -957,6 +990,7 @@ class DatabaseIntegrityController default: $out = htmlspecialchars($fieldValue); } + return $out; } @@ -1144,6 +1178,7 @@ class DatabaseIntegrityController } } } + return $out; } @@ -1179,6 +1214,7 @@ class DatabaseIntegrityController } $first = false; } + return $qs; } @@ -1228,6 +1264,7 @@ class DatabaseIntegrityController $qsTmp = str_replace('#VALUE1#', trim($queryBuilder->quote((string)$inputVal), '\''), $qsTmp); } $qs .= trim((string)$qsTmp); + return $qs; } @@ -1261,6 +1298,7 @@ class DatabaseIntegrityController // fallback to float casting, the whole class smells like it needs a refactoring. $inputVal = (float)($var ?? 0.0); } + return $inputVal; } @@ -1286,6 +1324,7 @@ class DatabaseIntegrityController } $format = 'Y-m-d\\TH:i:s\\Z'; $formattedDate = \DateTime::createFromFormat($format, (string)$date); + return $formattedDate && $formattedDate->format($format) === $date; } @@ -1298,12 +1337,8 @@ class DatabaseIntegrityController // Make output if (in_array('table', $enableArr) && !($userTsConfig['mod.']['dbint.']['disableSelectATable'] ?? false)) { $out[] = '<div class="form-group">'; - $out[] = '<label for="SET[queryTable]">Select a table:</label>'; - $out[] = '<div class="row row-cols-auto">'; - $out[] = '<div class="col">'; - $out[] = $this->mkTableSelect('SET[queryTable]', $this->table); - $out[] = '</div>'; - $out[] = '</div>'; + $out[] = '<label class="form-label" for="SET[queryTable]">Select a table:</label>'; + $out[] = $this->mkTableSelect('SET[queryTable]', $this->table); $out[] = '</div>'; } if ($this->table) { @@ -1341,67 +1376,61 @@ class DatabaseIntegrityController $codeArr = $this->getFormElements(); $queryCode = $this->printCodeArray($codeArr); if (in_array('fields', $enableArr) && !($userTsConfig['mod.']['dbint.']['disableSelectFields'] ?? false)) { - $out[] = '<div class="form-group form-group-with-button-addon">'; - $out[] = ' <label for="SET[queryFields]">Select fields:</label>'; + $out[] = '<div class="form-group">'; + $out[] = '<label class="form-label" for="SET[queryFields]">Select fields:</label>'; $out[] = $this->mkFieldToInputSelect('SET[queryFields]', $this->extFieldLists['queryFields']); $out[] = '</div>'; } if (in_array('query', $enableArr) && !($userTsConfig['mod.']['dbint.']['disableMakeQuery'] ?? false)) { $out[] = '<div class="form-group">'; - $out[] = ' <label>Make Query:</label>'; + $out[] = '<label class="form-label">Make Query:</label>'; $out[] = $queryCode; $out[] = '</div>'; } if (in_array('group', $enableArr) && !($userTsConfig['mod.']['dbint.']['disableGroupBy'] ?? false)) { $out[] = '<div class="form-group">'; - $out[] = '<label for="SET[queryGroup]">Group By:</label>'; - $out[] = '<div class="row row-cols-auto">'; - $out[] = '<div class="col">'; - $out[] = $this->mkTypeSelect('SET[queryGroup]', $this->extFieldLists['queryGroup'], ''); - $out[] = '</div>'; - $out[] = '</div>'; + $out[] = '<label class="form-label" for="SET[queryGroup]">Group By:</label>'; + $out[] = $this->mkTypeSelect('SET[queryGroup]', $this->extFieldLists['queryGroup'], ''); $out[] = '</div>'; } if (in_array('order', $enableArr) && !($userTsConfig['mod.']['dbint.']['disableOrderBy'] ?? false)) { $orderByArr = explode(',', $this->extFieldLists['queryOrder']); $orderBy = []; - $orderBy[] = '<div class="row row-cols-auto align-items-center">'; - $orderBy[] = '<div class="col">'; - $orderBy[] = $this->mkTypeSelect('SET[queryOrder]', $orderByArr[0], ''); - $orderBy[] = '</div>'; - $orderBy[] = '<div class="col mt-2">'; - $orderBy[] = '<div class="form-check">'; - $orderBy[] = self::getFuncCheck(0, 'SET[queryOrderDesc]', $modSettings['queryOrderDesc'] ?? '', $request, '', '', 'id="checkQueryOrderDesc"'); - $orderBy[] = '<label class="form-check-label" for="checkQueryOrderDesc">Descending</label>'; - $orderBy[] = '</div>'; + $orderBy[] = '<div class="form-group">'; + $orderBy[] = '<div class="input-group">'; + $orderBy[] = $this->mkTypeSelect('SET[queryOrder]', $orderByArr[0], ''); + $orderBy[] = '<div class="input-group-text">'; + $orderBy[] = '<div class="form-check form-check-type-toggle">'; + $orderBy[] = self::getFuncCheck(0, 'SET[queryOrderDesc]', $modSettings['queryOrderDesc'] ?? '', $request, '', '', 'id="checkQueryOrderDesc"'); + $orderBy[] = '<label class="form-check-label" for="checkQueryOrderDesc">Descending</label>'; + $orderBy[] = '</div>'; $orderBy[] = '</div>'; + $orderBy[] = '</div>'; $orderBy[] = '</div>'; if ($orderByArr[0]) { - $orderBy[] = '<div class="row row-cols-auto align-items-center mt-2">'; - $orderBy[] = '<div class="col">'; - $orderBy[] = '<div class="input-group">'; - $orderBy[] = $this->mkTypeSelect('SET[queryOrder2]', $orderByArr[1] ?? '', ''); - $orderBy[] = '</div>'; - $orderBy[] = '</div>'; - $orderBy[] = '<div class="col mt-2">'; - $orderBy[] = '<div class="form-check">'; - $orderBy[] = self::getFuncCheck(0, 'SET[queryOrder2Desc]', $modSettings['queryOrder2Desc'] ?? false, $request, '', '', 'id="checkQueryOrder2Desc"'); - $orderBy[] = '<label class="form-check-label" for="checkQueryOrder2Desc">Descending</label>'; - $orderBy[] = '</div>'; + $orderBy[] = '<div class="form-group">'; + $orderBy[] = '<div class="input-group">'; + $orderBy[] = $this->mkTypeSelect('SET[queryOrder2]', $orderByArr[1] ?? '', ''); + $orderBy[] = '<div class="input-group-text">'; + $orderBy[] = '<div class="form-check form-check-type-toggle">'; + $orderBy[] = self::getFuncCheck(0, 'SET[queryOrder2Desc]', $modSettings['queryOrder2Desc'] ?? false, $request, '', '', 'id="checkQueryOrder2Desc"'); + $orderBy[] = '<label class="form-check-label" for="checkQueryOrder2Desc">Descending</label>'; + $orderBy[] = '</div>'; $orderBy[] = '</div>'; + $orderBy[] = '</div>'; $orderBy[] = '</div>'; } $out[] = '<div class="form-group">'; - $out[] = ' <label>Order By:</label>'; - $out[] = implode(LF, $orderBy); + $out[] = ' <label class="form-label">Order By:</label>'; + $out[] = implode(LF, $orderBy); $out[] = '</div>'; } if (in_array('limit', $enableArr) && !($userTsConfig['mod.']['dbint.']['disableLimit'] ?? false)) { $limit = []; $limit[] = '<div class="input-group">'; - $limit[] = $this->updateIcon(); - $limit[] = '<input type="text" class="form-control" value="' . htmlspecialchars($this->extFieldLists['queryLimit']) . '" name="SET[queryLimit]" id="queryLimit">'; + $limit[] = $this->updateIcon(); + $limit[] = '<input type="text" class="form-control" value="' . htmlspecialchars($this->extFieldLists['queryLimit']) . '" name="SET[queryLimit]" id="queryLimit">'; $limit[] = '</div>'; $prevLimit = $limitBegin - $limitLength < 0 ? 0 : $limitBegin - $limitLength; @@ -1424,29 +1453,30 @@ class DatabaseIntegrityController } $out[] = '<div class="form-group">'; - $out[] = ' <label>Limit:</label>'; - $out[] = ' <div class="row row-cols-auto">'; - $out[] = ' <div class="col">'; + $out[] = ' <label class="form-label">Limit:</label>'; + $out[] = ' <div class="form-row">'; + $out[] = ' <div class="form-group">'; $out[] = implode(LF, $limit); - $out[] = ' </div>'; - $out[] = ' <div class="col">'; - $out[] = ' <div class="btn-group t3js-limit-submit">'; - $out[] = $prevButton; - $out[] = $nextButton; - $out[] = ' </div>'; - $out[] = ' </div>'; - $out[] = ' <div class="col">'; - $out[] = ' <div class="btn-group t3js-limit-submit">'; - $out[] = ' <input type="button" class="btn btn-default" data-value="10" value="10">'; - $out[] = ' <input type="button" class="btn btn-default" data-value="20" value="20">'; - $out[] = ' <input type="button" class="btn btn-default" data-value="50" value="50">'; - $out[] = ' <input type="button" class="btn btn-default" data-value="100" value="100">'; - $out[] = ' </div>'; - $out[] = ' </div>'; - $out[] = ' </div>'; + $out[] = ' </div>'; + $out[] = ' <div class="form-group">'; + $out[] = ' <div class="btn-group t3js-limit-submit">'; + $out[] = $prevButton; + $out[] = $nextButton; + $out[] = ' </div>'; + $out[] = ' </div>'; + $out[] = ' <div class="form-group">'; + $out[] = ' <div class="btn-group t3js-limit-submit">'; + $out[] = ' <input type="button" class="btn btn-default" data-value="10" value="10">'; + $out[] = ' <input type="button" class="btn btn-default" data-value="20" value="20">'; + $out[] = ' <input type="button" class="btn btn-default" data-value="50" value="50">'; + $out[] = ' <input type="button" class="btn btn-default" data-value="100" value="100">'; + $out[] = ' </div>'; + $out[] = ' </div>'; + $out[] = ' </div>'; $out[] = '</div>'; } } + return implode(LF, $out); } @@ -1492,6 +1522,7 @@ class DatabaseIntegrityController $queryConfig[$key]['inputValue1'] = $this->cleanInputVal($queryConfig[$key], '1'); } } + return $queryConfig; } @@ -1506,6 +1537,7 @@ class DatabaseIntegrityController return $key; } } + return $first; } @@ -1524,6 +1556,7 @@ class DatabaseIntegrityController return $i; } } + return $first; } @@ -1575,7 +1608,7 @@ class DatabaseIntegrityController $lineHTML[] = ''; break; case 'date': - $lineHTML[] = '<div class="row row-cols-auto mb-2 mb-sm-0">'; + $lineHTML[] = '<div class="form-row">'; $lineHTML[] = $this->makeComparisonSelector($subscript, $fieldName, $conf); if ($conf['comparison'] === 100 || $conf['comparison'] === 101) { // between @@ -1587,7 +1620,7 @@ class DatabaseIntegrityController $lineHTML[] = '</div>'; break; case 'time': - $lineHTML[] = '<div class="row row-cols-auto mb-2 mb-sm-0">'; + $lineHTML[] = '<div class="form-row">'; $lineHTML[] = $this->makeComparisonSelector($subscript, $fieldName, $conf); if ($conf['comparison'] === 100 || $conf['comparison'] === 101) { // between: @@ -1601,16 +1634,16 @@ class DatabaseIntegrityController case 'multiple': case 'binary': case 'relation': - $lineHTML[] = '<div class="row row-cols-auto mb-2 mb-sm-0">'; + $lineHTML[] = '<div class="form-row">'; $lineHTML[] = $this->makeComparisonSelector($subscript, $fieldName, $conf); - $lineHTML[] = '<div class="col mb-sm-2">'; + $lineHTML[] = '<div class="form-group">'; if ($conf['comparison'] === 68 || $conf['comparison'] === 69 || $conf['comparison'] === 162 || $conf['comparison'] === 163) { $lineHTML[] = '<select class="form-select" name="' . $fieldPrefix . '[inputValue][]" multiple="multiple">'; } elseif ($conf['comparison'] === 66 || $conf['comparison'] === 67) { if (is_array($conf['inputValue'])) { $conf['inputValue'] = implode(',', $conf['inputValue']); } - $lineHTML[] = '<input class="form-control t3js-clearable" type="text" value="' . htmlspecialchars($conf['inputValue'] ?? '') . '" name="' . $fieldPrefix . '[inputValue]">'; + $lineHTML[] = '<input class="form-control form-control-clearable t3js-clearable" type="text" value="' . htmlspecialchars($conf['inputValue'] ?? '') . '" name="' . $fieldPrefix . '[inputValue]">'; } elseif ($conf['comparison'] === 64) { if (is_array($conf['inputValue'])) { $conf['inputValue'] = $conf['inputValue'][0]; @@ -1627,41 +1660,60 @@ class DatabaseIntegrityController $lineHTML[] = '</div>'; break; case 'boolean': - $lineHTML[] = '<div class="row row-cols-auto mb-2 mb-sm-0">'; + $lineHTML[] = '<div class="form-row">'; $lineHTML[] = $this->makeComparisonSelector($subscript, $fieldName, $conf); $lineHTML[] = '<input type="hidden" value="1" name="' . $fieldPrefix . '[inputValue]">'; $lineHTML[] = '</div>'; break; default: - $lineHTML[] = '<div class="row row-cols-auto mb-2 mb-sm-0">'; + $lineHTML[] = '<div class="form-row">'; $lineHTML[] = $this->makeComparisonSelector($subscript, $fieldName, $conf); - $lineHTML[] = '<div class="col mb-sm-2">'; if ($conf['comparison'] === 37 || $conf['comparison'] === 36) { // between: - $lineHTML[] = '<input class="form-control t3js-clearable" type="text" value="' . htmlspecialchars($conf['inputValue'] ?? '') . '" name="' . $fieldPrefix . '[inputValue]">'; - $lineHTML[] = '<input class="form-control t3js-clearable" type="text" value="' . htmlspecialchars($conf['inputValue1'] ?? '') . '" name="' . $fieldPrefix . '[inputValue1]">'; + $lineHTML[] = '<div class="form-group">'; + $lineHTML[] = ' <input class="form-control form-control-clearable t3js-clearable" type="text" value="' . htmlspecialchars($conf['inputValue'] ?? '') . '" name="' . $fieldPrefix . '[inputValue]">'; + $lineHTML[] = '</div>'; + $lineHTML[] = '<div class="form-group">'; + $lineHTML[] = ' <input class="form-control form-control-clearable t3js-clearable" type="text" value="' . htmlspecialchars($conf['inputValue1'] ?? '') . '" name="' . $fieldPrefix . '[inputValue1]">'; + $lineHTML[] = '</div>'; } else { - $lineHTML[] = '<input class="form-control t3js-clearable" type="text" value="' . htmlspecialchars($conf['inputValue'] ?? '') . '" name="' . $fieldPrefix . '[inputValue]">'; + $lineHTML[] = '<div class="form-group">'; + $lineHTML[] = ' <input class="form-control form-control-clearable t3js-clearable" type="text" value="' . htmlspecialchars($conf['inputValue'] ?? '') . '" name="' . $fieldPrefix . '[inputValue]">'; + $lineHTML[] = '</div>'; } $lineHTML[] = '</div>'; - $lineHTML[] = '</div>'; } if ($fieldType !== 'ignore') { - $lineHTML[] = '<div class="row row-cols-auto mb-2">'; + $lineHTML[] = '<div class="form-row">'; $lineHTML[] = '<div class="btn-group">'; $lineHTML[] = $this->updateIcon(); if ($loopCount) { - $lineHTML[] = '<button class="btn btn-default" title="Remove condition" name="qG_del' . htmlspecialchars($subscript) . '">' . $this->iconFactory->getIcon('actions-delete', Icon::SIZE_SMALL)->render() . '</button>'; + $lineHTML[] = '' + . '<button class="btn btn-default" title="Remove condition" name="qG_del' . htmlspecialchars($subscript) . '">' + . $this->iconFactory->getIcon('actions-delete', Icon::SIZE_SMALL)->render() + . '</button>'; } - $lineHTML[] = '<button class="btn btn-default" title="Add condition" name="qG_ins' . htmlspecialchars($subscript) . '">' . $this->iconFactory->getIcon('actions-plus', Icon::SIZE_SMALL)->render() . '</button>'; + $lineHTML[] = '' + . '<button class="btn btn-default" title="Add condition" name="qG_ins' . htmlspecialchars($subscript) . '">' + . $this->iconFactory->getIcon('actions-plus', Icon::SIZE_SMALL)->render() + . '</button>'; if ($c != 0) { - $lineHTML[] = '<button class="btn btn-default" title="Move up" name="qG_up' . htmlspecialchars($subscript) . '">' . $this->iconFactory->getIcon('actions-chevron-up', Icon::SIZE_SMALL)->render() . '</button>'; + $lineHTML[] = '' + . '<button class="btn btn-default" title="Move up" name="qG_up' . htmlspecialchars($subscript) . '">' + . $this->iconFactory->getIcon('actions-chevron-up', Icon::SIZE_SMALL)->render() + . '</button>'; } if ($c != 0 && $fieldType !== 'newlevel') { - $lineHTML[] = '<button class="btn btn-default" title="New level" name="qG_nl' . htmlspecialchars($subscript) . '">' . $this->iconFactory->getIcon('actions-chevron-right', Icon::SIZE_SMALL)->render() . '</button>'; + $lineHTML[] = '' + . '<button class="btn btn-default" title="New level" name="qG_nl' . htmlspecialchars($subscript) . '">' + . $this->iconFactory->getIcon('actions-chevron-right', Icon::SIZE_SMALL)->render() + . '</button>'; } if ($fieldType === 'newlevel') { - $lineHTML[] = '<button class="btn btn-default" title="Collapse new level" name="qG_remnl' . htmlspecialchars($subscript) . '">' . $this->iconFactory->getIcon('actions-chevron-left', Icon::SIZE_SMALL)->render() . '</button>'; + $lineHTML[] = '' + . '<button class="btn btn-default" title="Collapse new level" name="qG_remnl' . htmlspecialchars($subscript) . '">' + . $this->iconFactory->getIcon('actions-chevron-left', Icon::SIZE_SMALL)->render() + . '</button>'; } $lineHTML[] = '</div>'; $lineHTML[] = '</div>'; @@ -1673,6 +1725,7 @@ class DatabaseIntegrityController $loopCount = 1; } $this->queryConfig = $queryConfig; + return $codeArr; } @@ -1681,15 +1734,16 @@ class DatabaseIntegrityController $value = strtotime($timestamp) ? date($GLOBALS['TYPO3_CONF_VARS']['SYS']['hhmm'] . ' ' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'], (int)strtotime($timestamp)) : ''; $id = StringUtility::getUniqueId('dt_'); $html = []; - $html[] = '<div class="col mb-sm-2">'; + $html[] = '<div class="form-group">'; $html[] = ' <div class="input-group" id="' . $id . '-wrapper">'; - $html[] = ' <input data-formengine-input-name="' . htmlspecialchars($name) . '" value="' . $value . '" class="form-control t3js-datetimepicker t3js-clearable" data-date-type="' . htmlspecialchars($type) . '" type="text" id="' . $id . '">'; + $html[] = ' <input data-formengine-input-name="' . htmlspecialchars($name) . '" value="' . $value . '" class="form-control form-control-clearable t3js-datetimepicker t3js-clearable" data-date-type="' . htmlspecialchars($type) . '" type="text" id="' . $id . '">'; $html[] = ' <input name="' . htmlspecialchars($name) . '" value="' . htmlspecialchars($timestamp) . '" type="hidden">'; $html[] = ' <button class="btn btn-default" type="button" data-global-event="click" data-action-focus="#' . $id . '">'; $html[] = $this->iconFactory->getIcon('actions-calendar-alternative', Icon::SIZE_SMALL)->render(); $html[] = ' </button>'; $html[] = ' </div>'; $html[] = '</div>'; + return implode(LF, $html); } @@ -1882,6 +1936,7 @@ class DatabaseIntegrityController } } } + return implode(LF, $out); } @@ -1889,17 +1944,16 @@ class DatabaseIntegrityController { $out = []; if ($draw) { - $out[] = '<div class="row row-cols-auto mb-2">'; - $out[] = ' <div class="col">'; - $out[] = ' <select class="form-select' . ($submit ? ' t3js-submit-change' : '') . '" name="' . htmlspecialchars($name) . '[operator]">'; - $out[] = ' <option value="AND"' . (!$op || $op === 'AND' ? ' selected' : '') . '>' . htmlspecialchars($this->lang['AND']) . '</option>'; - $out[] = ' <option value="OR"' . ($op === 'OR' ? ' selected' : '') . '>' . htmlspecialchars($this->lang['OR']) . '</option>'; - $out[] = ' </select>'; - $out[] = ' </div>'; + $out[] = '<div class="form-group">'; + $out[] = ' <select class="form-select' . ($submit ? ' t3js-submit-change' : '') . '" name="' . htmlspecialchars($name) . '[operator]">'; + $out[] = ' <option value="AND"' . (!$op || $op === 'AND' ? ' selected' : '') . '>' . htmlspecialchars($this->lang['AND']) . '</option>'; + $out[] = ' <option value="OR"' . ($op === 'OR' ? ' selected' : '') . '>' . htmlspecialchars($this->lang['OR']) . '</option>'; + $out[] = ' </select>'; $out[] = '</div>'; } else { $out[] = '<input type="hidden" value="' . htmlspecialchars($op) . '" name="' . htmlspecialchars($name) . '[operator]">'; } + return implode(LF, $out); } @@ -1907,17 +1961,20 @@ class DatabaseIntegrityController { $fieldPrefix = $this->name . $subscript; $lineHTML = []; - $lineHTML[] = '<div class="col mb-sm-2">'; - $lineHTML[] = $this->mkTypeSelect($fieldPrefix . '[type]', $fieldName); + $lineHTML[] = '<div class="form-group">'; + $lineHTML[] = $this->mkTypeSelect($fieldPrefix . '[type]', $fieldName); $lineHTML[] = '</div>'; - $lineHTML[] = '<div class="col mb-sm-2">'; - $lineHTML[] = ' <div class="input-group">'; - $lineHTML[] = $this->mkCompSelect($fieldPrefix . '[comparison]', (string)$conf['comparison'], ($conf['negate'] ?? null) ? 1 : 0); - $lineHTML[] = ' <span class="input-group-addon">'; - $lineHTML[] = ' <input type="checkbox" class="checkbox t3js-submit-click"' . (($conf['negate'] ?? null) ? ' checked' : '') . ' name="' . htmlspecialchars($fieldPrefix) . '[negate]">'; - $lineHTML[] = ' </span>'; - $lineHTML[] = ' </div>'; + $lineHTML[] = '<div class="form-group">'; + $lineHTML[] = ' <div class="input-group">'; + $lineHTML[] = $this->mkCompSelect($fieldPrefix . '[comparison]', (string)$conf['comparison'], ($conf['negate'] ?? null) ? 1 : 0); + $lineHTML[] = ' <span class="input-group-addon">'; + $lineHTML[] = ' <div class="form-check form-check-type-toggle">'; + $lineHTML[] = ' <input type="checkbox" class="form-check-input t3js-submit-click"' . (($conf['negate'] ?? null) ? ' checked' : '') . ' name="' . htmlspecialchars($fieldPrefix) . '[negate]">'; + $lineHTML[] = ' </div>'; + $lineHTML[] = ' </span>'; + $lineHTML[] = ' </div>'; $lineHTML[] = '</div>'; + return implode(LF, $lineHTML); } @@ -1932,6 +1989,7 @@ class DatabaseIntegrityController } } $out[] = '</select>'; + return implode(LF, $out); } @@ -1940,37 +1998,33 @@ class DatabaseIntegrityController $out = []; foreach (array_values($codeArr) as $queryComponent) { $out[] = '<div class="card">'; - $out[] = '<div class="card-body pb-2">'; + $out[] = '<div class="card-body">'; $out[] = $queryComponent['html']; if ($this->enableQueryParts) { - $out[] = '<div class="row row-cols-auto mb-2">'; - $out[] = '<div class="col">'; - $out[] = '<code class="m-0">'; - $out[] = htmlspecialchars($queryComponent['query']); - $out[] = '</code>'; - $out[] = '</div>'; - $out[] = '</div>'; + $out[] = '<pre class="language-sql">'; + $out[] = '<code class="language-sql">'; + $out[] = htmlspecialchars($queryComponent['query']); + $out[] = '</code>'; + $out[] = '</pre>'; } if (is_array($queryComponent['sub'] ?? null)) { - $out[] = '<div class="mb-2">'; - $out[] = $this->printCodeArray($queryComponent['sub'], $recursionLevel + 1); - $out[] = '</div>'; + $out[] = $this->printCodeArray($queryComponent['sub'], $recursionLevel + 1); } $out[] = '</div>'; $out[] = '</div>'; } + return implode(LF, $out); } protected function mkFieldToInputSelect(string $name, string $fieldName): string { $out = []; - $out[] = '<div class="input-group mb-2">'; - $out[] = $this->updateIcon(); - $out[] = '<input type="text" class="form-control t3js-clearable" value="' . htmlspecialchars($fieldName) . '" name="' . htmlspecialchars($name) . '">'; + $out[] = '<div class="input-group mb-1">'; + $out[] = $this->updateIcon(); + $out[] = '<input type="text" class="form-control form-control-clearable t3js-clearable" value="' . htmlspecialchars($fieldName) . '" name="' . htmlspecialchars($name) . '">'; $out[] = '</div>'; - $out[] = '<select class="form-select t3js-addfield" name="_fieldListDummy" size="5" data-field="' . htmlspecialchars($name) . '">'; foreach ($this->fields as $key => $value) { if (!$value['exclude'] || $this->getBackendUserAuthentication()->check('non_exclude_fields', $this->table . ':' . $key)) { @@ -1982,6 +2036,7 @@ class DatabaseIntegrityController } } $out[] = '</select>'; + return implode(LF, $out); } @@ -2101,6 +2156,7 @@ class DatabaseIntegrityController break; } } + return $retArr; } @@ -2124,6 +2180,7 @@ class DatabaseIntegrityController } } $out[] = '</select>'; + return implode(LF, $out); } @@ -2159,6 +2216,7 @@ class DatabaseIntegrityController } } $out[] = '</select>'; + return implode(LF, $out); } @@ -2321,6 +2379,7 @@ class DatabaseIntegrityController $fieldListArr[] = $GLOBALS['TCA'][$this->table]['ctrl']['sortby']; } } + return implode(',', $fieldListArr); } @@ -2335,23 +2394,26 @@ class DatabaseIntegrityController } $markup = []; - $markup[] = '<div class="load-queries">'; - $markup[] = ' <div class="row row-cols-auto">'; - $markup[] = ' <div class="col">'; - $markup[] = ' <select class="form-select" name="storeControl[STORE]" data-assign-store-control-title>' . implode(LF, $opt) . '</select>'; - $markup[] = ' </div>'; - $markup[] = ' <div class="col">'; - $markup[] = ' <input class="form-control" name="storeControl[title]" value="" type="text" max="80">'; - $markup[] = ' </div>'; - $markup[] = ' <div class="col">'; - $markup[] = ' <input class="btn btn-default" type="submit" name="storeControl[LOAD]" value="Load">'; - $markup[] = ' </div>'; - $markup[] = ' <div class="col">'; - $markup[] = ' <input class="btn btn-default" type="submit" name="storeControl[SAVE]" value="Save">'; - $markup[] = ' </div>'; - $markup[] = ' <div class="col">'; - $markup[] = ' <input class="btn btn-default" type="submit" name="storeControl[REMOVE]" value="Remove">'; - $markup[] = ' </div>'; + $markup[] = '<div class="form-row">'; + $markup[] = ' <div class="form-group">'; + $markup[] = ' <select class="form-select" name="storeControl[STORE]" data-assign-store-control-title>' . implode(LF, $opt) . '</select>'; + $markup[] = ' </div>'; + $markup[] = ' <div class="form-group">'; + $markup[] = ' <input class="form-control" name="storeControl[title]" value="" type="text" max="80">'; + $markup[] = ' </div>'; + $markup[] = ' <div class="form-group">'; + $markup[] = ' <button class="btn btn-default" type="submit" name="storeControl[LOAD]" value="Load">'; + $markup[] = $this->iconFactory->getIcon('actions-upload', Icon::SIZE_SMALL)->render(); + $markup[] = ' Load'; + $markup[] = ' </button>'; + $markup[] = ' <button class="btn btn-default" type="submit" name="storeControl[SAVE]" value="Save">'; + $markup[] = $this->iconFactory->getIcon('actions-save', Icon::SIZE_SMALL)->render(); + $markup[] = ' Save'; + $markup[] = ' </button>'; + $markup[] = ' <button class="btn btn-default" type="submit" name="storeControl[REMOVE]" value="Remove">'; + $markup[] = $this->iconFactory->getIcon('actions-delete', Icon::SIZE_SMALL)->render(); + $markup[] = ' Remove'; + $markup[] = ' </button>'; $markup[] = ' </div>'; $markup[] = '</div>'; @@ -2425,6 +2487,7 @@ class DatabaseIntegrityController 'ses' ); } + return $msg; } @@ -2437,6 +2500,7 @@ class DatabaseIntegrityController } } } + return $storeQueryConfigs; } @@ -2447,6 +2511,7 @@ class DatabaseIntegrityController foreach ($keyArr as $k) { $storeQueryConfigs[$index][$k] = $this->MOD_SETTINGS[$k] ?? null; } + return $storeQueryConfigs; } @@ -2458,6 +2523,7 @@ class DatabaseIntegrityController $writeArray[$k] = $storeQueryConfigs[$storeIndex][$k]; } } + return $writeArray; } @@ -2470,6 +2536,7 @@ class DatabaseIntegrityController if (is_array($savedStoreArray)) { $storeArray = array_merge($storeArray, $savedStoreArray); } + return $storeArray; } @@ -2477,12 +2544,12 @@ class DatabaseIntegrityController { $markup = []; $markup[] = '<div class="form-group">'; - $markup[] = '<input placeholder="Search Word" class="form-control" type="search" name="SET[sword]" value="' - . htmlspecialchars($this->MOD_SETTINGS['sword'] ?? '') . '">'; + $markup[] = '<input placeholder="Search Word" class="form-control" type="search" name="SET[sword]" value="' . htmlspecialchars($this->MOD_SETTINGS['sword'] ?? '') . '">'; $markup[] = '</div>'; $markup[] = '<div class="form-group">'; - $markup[] = '<input class="btn btn-default" type="submit" name="submit" value="Search All Records">'; + $markup[] = '<input class="btn btn-default" type="submit" name="submit" value="Search All Records">'; $markup[] = '</div>'; + return implode(LF, $markup); } @@ -2587,6 +2654,7 @@ class DatabaseIntegrityController } } } + return $out; } @@ -2704,6 +2772,7 @@ class DatabaseIntegrityController 'doktypes' => $doktypes, 'tables' => $tableStatistic, ]); + return $view->renderResponse('RecordStatistics'); } @@ -2718,6 +2787,7 @@ class DatabaseIntegrityController 'select_db' => $databaseIntegrityCheck->testDBRefs($databaseIntegrityCheck->getCheckSelectDBRefs()), 'group_db' => $databaseIntegrityCheck->testDBRefs($databaseIntegrityCheck->getCheckGroupDBRefs()), ]); + return $view->renderResponse('Relations'); } @@ -2782,13 +2852,11 @@ class DatabaseIntegrityController 'data-action-navigate' => '$data=~s/$value/', 'data-navigate-value' => $scriptUrl . '&' . $elementName . '=${value}', ], $additionalAttributes), true); + return ' - <div class="input-group"> - <!-- Function Menu of module --> <select class="form-select" ' . $attributes . '> ' . implode(LF, $options) . ' - </select> - </div>'; + </select>'; } /** @@ -2825,6 +2893,7 @@ class DatabaseIntegrityController 'data-navigate-value' => sprintf('%s&%s=${value}', $scriptUrl, $elementName), 'data-empty-value' => '0', ], true); + return '<input ' . $attributes . ($currentValue ? ' checked="checked"' : '') . diff --git a/typo3/sysext/lowlevel/Resources/Private/Templates/Configuration.html b/typo3/sysext/lowlevel/Resources/Private/Templates/Configuration.html index 8e06404debbe..dac60a5038bc 100644 --- a/typo3/sysext/lowlevel/Resources/Private/Templates/Configuration.html +++ b/typo3/sysext/lowlevel/Resources/Private/Templates/Configuration.html @@ -24,13 +24,13 @@ <h2>{treeName}</h2> - <div id="lowlevel-config" class="row row-cols-auto mb-3"> - <div class="col"> + <div id="lowlevel-config" class="form-row"> + <div class="form-group"> <form action="#"> <div class="input-group"> <input type="text" - class="form-control t3js-collapse-search-term" + class="form-control form-control-clearable t3js-collapse-search-term" name="searchValue" id="searchValue" data-persist-collapse-search-key="collapse-search-term-lowlevel-configuration-{treeLabelHash}" @@ -42,12 +42,12 @@ </div> </form> </div> - <div class="col d-flex align-items-center"> + <div class="d-flex align-items-center"> <span class="badge badge-success hidden t3js-collapse-states-search-numberOfSearchMatches"></span> </div> </div> - <div class="nowrap t3js-collapse-states-search-tree"> + <div class="t3js-collapse-states-search-tree"> <f:format.raw>{tree}</f:format.raw> </div> </form> diff --git a/typo3/sysext/lowlevel/Resources/Private/Templates/CustomSearch.html b/typo3/sysext/lowlevel/Resources/Private/Templates/CustomSearch.html index c19b0ae09c00..3e87b128c636 100644 --- a/typo3/sysext/lowlevel/Resources/Private/Templates/CustomSearch.html +++ b/typo3/sysext/lowlevel/Resources/Private/Templates/CustomSearch.html @@ -5,8 +5,7 @@ <f:layout name="Module" /> -<f:section name="Content"> - +<f:section name="Before"> <f:if condition="{searchMode} == 'query'"> <f:be.pageRenderer includeJavaScriptModules="{ @@ -14,25 +13,33 @@ }" /> </f:if> +</f:section> - <h1>{f:translate(key:'LLL:EXT:lowlevel/Resources/Private/Language/locallang.xlf:search_whole_database')}</h1> +<f:section name="Content"> + <h1>{f:translate(key:'LLL:EXT:lowlevel/Resources/Private/Language/locallang.xlf:search_whole_database')}</h1> <f:format.raw>{submenu}</f:format.raw> + + <f:if condition="{searchMode} != 'query'"> + <h2>{f:translate(key:'LLL:EXT:lowlevel/Resources/Private/Language/locallang.xlf:searchOptions')}</h2> + </f:if> + <form action="" method="post" id="DatabaseIntegrityView" name="queryform"> <f:if condition="{searchMode} == 'query'"> <f:then> <f:format.raw>{queryMaker}</f:format.raw> </f:then> <f:else> - <h2>{f:translate(key:'LLL:EXT:lowlevel/Resources/Private/Language/locallang.xlf:searchOptions')}</h2> <f:format.raw>{searchOptions}</f:format.raw> - - <h2>{f:translate(key:'LLL:EXT:lowlevel/Resources/Private/Language/locallang.xlf:result')}</h2> - <f:format.raw>{results}</f:format.raw> </f:else> </f:if> </form> + <f:if condition="{results}"> + <h2>{f:translate(key:'LLL:EXT:lowlevel/Resources/Private/Language/locallang.xlf:result')}</h2> + <f:format.raw>{results}</f:format.raw> + </f:if> + </f:section> </html> diff --git a/typo3/sysext/lowlevel/Resources/Public/JavaScript/query-generator.js b/typo3/sysext/lowlevel/Resources/Public/JavaScript/query-generator.js index 2a6ea5ccd1e7..bb00a4ce3057 100644 --- a/typo3/sysext/lowlevel/Resources/Public/JavaScript/query-generator.js +++ b/typo3/sysext/lowlevel/Resources/Public/JavaScript/query-generator.js @@ -10,4 +10,4 @@ * * The TYPO3 project - inspiring people to share! */ -import $ from"jquery";import"@typo3/backend/input/clearable.js";import DateTimePicker from"@typo3/backend/date-time-picker.js";class QueryGenerator{constructor(){this.form=null,this.limitField=null,this.initialize()}initialize(){this.form=$('form[name="queryform"]'),this.limitField=$("#queryLimit"),this.form.on("click",".t3js-submit-click",(t=>{t.preventDefault(),this.doSubmit()})),this.form.on("change",".t3js-submit-change",(t=>{t.preventDefault(),this.doSubmit()})),this.form.on("click",'.t3js-limit-submit input[type="button"]',(t=>{t.preventDefault(),this.setLimit($(t.currentTarget).data("value")),this.doSubmit()})),this.form.on("click",".t3js-addfield",(t=>{t.preventDefault();const e=$(t.currentTarget);this.addValueToField(e.data("field"),e.val())})),this.form.on("change","[data-assign-store-control-title]",(t=>{const e=$(t.currentTarget),i=this.form.find('[name="storeControl[title]"]');"0"!==e.val()?i.val(e.find("option:selected").text()):i.val("")})),document.querySelectorAll('form[name="queryform"] .t3js-clearable').forEach((t=>t.clearable({onClear:()=>{this.doSubmit()}}))),document.querySelectorAll('form[name="queryform"] .t3js-datetimepicker').forEach((t=>DateTimePicker.initialize(t)))}doSubmit(){this.form.trigger("submit")}setLimit(t){this.limitField.val(t)}addValueToField(t,e){const i=this.form.find('[name="'+t+'"]'),r=i.val();i.val(r+","+e)}}export default new QueryGenerator; \ No newline at end of file +import"@typo3/backend/input/clearable.js";import DateTimePicker from"@typo3/backend/date-time-picker.js";import RegularEvent from"@typo3/core/event/regular-event.js";class QueryGenerator{constructor(){this.form=null,this.limitField=null,this.form=document.querySelector('form[name="queryform"]'),this.limitField=document.querySelector("input#queryLimit"),new RegularEvent("click",(e=>{e.preventDefault(),this.doSubmit()})).delegateTo(this.form,".t3js-submit-click"),new RegularEvent("change",(e=>{e.preventDefault(),this.doSubmit()})).delegateTo(this.form,".t3js-submit-change"),new RegularEvent("click",((e,t)=>{e.preventDefault(),this.setLimit(t.value),this.doSubmit()})).delegateTo(this.form,'.t3js-limit-submit input[type="button"]'),new RegularEvent("click",((e,t)=>{e.preventDefault(),this.addValueToField(t.dataset.field,t.value)})).delegateTo(this.form,".t3js-addfield"),new RegularEvent("change",((e,t)=>{const i=this.form.querySelector('input[name="storeControl[title]"]');"0"!==t.value?i.value=t.querySelector("option:selected").textContent:i.value=""})).delegateTo(this.form,"select.t3js-addfield"),document.querySelectorAll('form[name="queryform"] .t3js-clearable').forEach((e=>e.clearable({onClear:()=>{this.doSubmit()}}))),document.querySelectorAll('form[name="queryform"] .t3js-datetimepicker').forEach((e=>DateTimePicker.initialize(e)))}doSubmit(){this.form.submit()}setLimit(e){this.limitField.value=e}addValueToField(e,t){const i=this.form.querySelector('[name="'+e+'"]');t=i.value+","+t,i.value=t.split(",").map((e=>e.trim())).filter(((e,t,i)=>i.indexOf(e)===t)).join(",")}}export default new QueryGenerator; \ No newline at end of file diff --git a/typo3/sysext/reactions/Resources/Private/Templates/Management/Overview.html b/typo3/sysext/reactions/Resources/Private/Templates/Management/Overview.html index a1c695fe15d7..7e1c4b6c4fd7 100644 --- a/typo3/sysext/reactions/Resources/Private/Templates/Management/Overview.html +++ b/typo3/sysext/reactions/Resources/Private/Templates/Management/Overview.html @@ -202,12 +202,12 @@ <form action="{f:be.uri(route:'system_reactions')}" method="post" enctype="multipart/form-data" name="demand"> <input type="hidden" name="orderField" value="{demand.orderField}"> <input type="hidden" name="orderDirection" value="{demand.orderDirection}"> - <div class="row row-cols-auto align-items-end g-3 mb-4"> - <div class="col"> + <div class="form-row"> + <div class="form-group"> <label for="demand-name" class="form-label"><f:translate key="LLL:EXT:reactions/Resources/Private/Language/locallang_module_reactions.xlf:filter.name"/></label> <input type="text" id="demand-name" class="form-control" name="demand[name]" value="{demand.name}"/> </div> - <div class="col"> + <div class="form-group"> <label for="demand-reaction-type" class="form-label"><f:translate key="LLL:EXT:reactions/Resources/Private/Language/locallang_module_reactions.xlf:filter.reaction_type"/></label> <select id="demand-reaction-type" class="form-select" name="demand[reaction_type]" data-on-change="submit"> <option value=""><f:translate key="LLL:EXT:reactions/Resources/Private/Language/locallang_module_reactions.xlf:filter.reaction_type.showAll"/></option> @@ -218,7 +218,7 @@ </f:for> </select> </div> - <div class="col"> + <div class="form-group align-self-end"> <input type="submit" value="{f:translate(key: 'LLL:EXT:reactions/Resources/Private/Language/locallang_module_reactions.xlf:filter.sendButton')}" class="btn btn-default" /> <a href="{f:be.uri(route:'system_reactions')}" class="btn btn-link"><f:translate key="LLL:EXT:reactions/Resources/Private/Language/locallang_module_reactions.xlf:filter.resetButton"/></a> </div> diff --git a/typo3/sysext/recycler/Resources/Private/Templates/RecyclerModule.html b/typo3/sysext/recycler/Resources/Private/Templates/RecyclerModule.html index edafc05e207a..11f32feb5cf3 100644 --- a/typo3/sysext/recycler/Resources/Private/Templates/RecyclerModule.html +++ b/typo3/sysext/recycler/Resources/Private/Templates/RecyclerModule.html @@ -12,14 +12,14 @@ <div id="recycler-index" class="tx_recycler_recycler"> <form id="recycler-form"> - <div class="row row-cols-auto align-items-end g-3 mb-4"> - <div class="col"> + <div class="form-row"> + <div class="form-group align-self-end"> <div class="input-group"> - <input type="text" name="search-text" class="form-control" placeholder="{f:translate(key: 'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.enterSearchString')}"> + <input type="text" name="search-text" class="form-control form-control-clearable" placeholder="{f:translate(key: 'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.enterSearchString')}"> <button type="submit" class="btn btn-default disabled"><core:icon identifier="actions-search" /></button> </div> </div> - <div class="col"> + <div class="form-group"> <label for="depth" class="form-label"><f:translate key="LLL:EXT:recycler/Resources/Private/Language/locallang.xlf:filter.depth" /></label> <select name="depth" id="depth" class="form-select"> <option value="0"><f:translate key="LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_0" /></option> @@ -30,7 +30,7 @@ <option value="999"><f:translate key="LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_infi" /></option> </select> </div> - <div class="col"> + <div class="form-group"> <label for="pages" class="form-label"><f:translate key="LLL:EXT:recycler/Resources/Private/Language/locallang.xlf:filter.type" /></label> <select name="pages" id="pages" class="form-select"></select> </div> diff --git a/typo3/sysext/redirects/Resources/Private/Templates/Management/Overview.html b/typo3/sysext/redirects/Resources/Private/Templates/Management/Overview.html index ea085d8e9f35..3474e1d2306e 100644 --- a/typo3/sysext/redirects/Resources/Private/Templates/Management/Overview.html +++ b/typo3/sysext/redirects/Resources/Private/Templates/Management/Overview.html @@ -228,8 +228,8 @@ <form action="{f:be.uri(route:'site_redirects', parameters: '{action: \'overview\'}')}" method="post" enctype="multipart/form-data" name="demand"> <input type="hidden" name="orderField" value="{demand.orderField}"> <input type="hidden" name="orderDirection" value="{demand.orderDirection}"> - <div class="row row-cols-auto align-items-end g-3 mb-4"> - <div class="col"> + <div class="form-row"> + <div class="form-group"> <label for="demand-source-host" class="form-label"><f:translate key="LLL:EXT:redirects/Resources/Private/Language/locallang_db.xlf:sys_redirect.source_host"/></label> <select id="demand-source-host" class="form-select" name="demand[source_host]" data-on-change="submit"> <option value=""><f:translate key="LLL:EXT:redirects/Resources/Private/Language/locallang_module_redirect.xlf:filter.source_host.showAll"/></option> @@ -238,15 +238,15 @@ </f:for> </select> </div> - <div class="col"> + <div class="form-group"> <label for="demand-source-path" class="form-label"><f:translate key="LLL:EXT:redirects/Resources/Private/Language/locallang_db.xlf:sys_redirect.source_path"/></label> <input type="text" id="demand-source-path" class="form-control" name="demand[source_path]" value="{demand.sourcePath}"/> </div> - <div class="col"> + <div class="form-group"> <label for="demand-target" class="form-label"><f:translate key="LLL:EXT:redirects/Resources/Private/Language/locallang_db.xlf:sys_redirect.target"/></label> <input type="text" id="demand-target" class="form-control" name="demand[target]" value="{demand.target}"/> </div> - <div class="col"> + <div class="form-group"> <label for="demand-target-status-code" class="form-label"><f:translate key="LLL:EXT:redirects/Resources/Private/Language/locallang_module_redirect.xlf:filter.targetStatusCode"/></label> <select id="demand-target-status-code" class="form-select" name="demand[target_statuscode]" data-on-change="submit"> <option value=""><f:translate key="LLL:EXT:redirects/Resources/Private/Language/locallang_module_redirect.xlf:filter.source_host.showAll"/></option> @@ -255,7 +255,7 @@ </f:for> </select> </div> - <div class="col"> + <div class="form-group"> <label for="demand-target-automatically-created" class="form-label"><f:translate key="LLL:EXT:redirects/Resources/Private/Language/locallang_module_redirect.xlf:filter.creationType"/></label> <select id="demand-target-automatically-created" class="form-select" name="demand[creation_type]" data-on-change="submit"> <option value="-1"><f:translate key="LLL:EXT:redirects/Resources/Private/Language/locallang_module_redirect.xlf:filter.creationType.showAll"/></option> @@ -265,14 +265,16 @@ </select> </div> <f:if condition="{showHitCounter}"> - <div class="form-check form-switch"> - <input type="checkbox" class="form-check-input" name="demand[max_hits]" id="demand-never-hit" value="1" data-on-change="submit" {f:if(condition: demand.maxHits, then: 'checked="checked"')}> - <label class="form-check-label" for="demand-never-hit"> - <f:translate key="LLL:EXT:redirects/Resources/Private/Language/locallang_module_redirect.xlf:filter.neverHit"/> - </label> + <div class="form-group align-self-end"> + <div class="form-check form-switch form-check-size-input"> + <input type="checkbox" class="form-check-input" name="demand[max_hits]" id="demand-never-hit" value="1" data-on-change="submit" {f:if(condition: demand.maxHits, then: 'checked="checked"')}> + <label class="form-check-label" for="demand-never-hit"> + <f:translate key="LLL:EXT:redirects/Resources/Private/Language/locallang_module_redirect.xlf:filter.neverHit"/> + </label> + </div> </div> </f:if> - <div class="col"> + <div class="form-group align-self-end"> <input type="submit" value="{f:translate(key: 'LLL:EXT:redirects/Resources/Private/Language/locallang_module_redirect.xlf:filter.sendButton')}" class="btn btn-default" /> <a href="{f:be.uri(route:'site_redirects')}" class="btn btn-link"><f:translate key="LLL:EXT:redirects/Resources/Private/Language/locallang_module_redirect.xlf:filter.resetButton"/></a> </div> diff --git a/typo3/sysext/scheduler/Resources/Private/Partials/AddEditStartEndFields.html b/typo3/sysext/scheduler/Resources/Private/Partials/AddEditStartEndFields.html index 97506ec2c0d6..d44fa7282dff 100644 --- a/typo3/sysext/scheduler/Resources/Private/Partials/AddEditStartEndFields.html +++ b/typo3/sysext/scheduler/Resources/Private/Partials/AddEditStartEndFields.html @@ -6,7 +6,7 @@ <input name="tx_scheduler[start]_hr" value="{f:format.date(format:'H:i d-m-Y', date:currentData.start)}" - class="form-control t3js-datetimepicker t3js-clearable" + class="form-control form-control-clearable t3js-datetimepicker t3js-clearable" data-date-type="datetime" data-date-offset="0" type="text" @@ -27,7 +27,7 @@ <input name="tx_scheduler[end]_hr" value="{formattedEnd}" - class="form-control t3js-datetimepicker t3js-clearable" + class="form-control form-control-clearable t3js-datetimepicker t3js-clearable" data-date-type="datetime" data-date-offset="0" type="text" diff --git a/typo3/sysext/setup/Resources/Private/Templates/Main.html b/typo3/sysext/setup/Resources/Private/Templates/Main.html index 3b478f27d58f..3500e480e8f9 100644 --- a/typo3/sysext/setup/Resources/Private/Templates/Main.html +++ b/typo3/sysext/setup/Resources/Private/Templates/Main.html @@ -5,19 +5,23 @@ <f:layout name="Module" /> -<f:section name="Content"> - +<f:section name="Before"> <f:be.pageRenderer includeJavaScriptModules="{ 0: '@typo3/backend/tabs.js' }" /> - <f:if condition="{isLanguageUpdate}"> <typo3-immediate-action action="TYPO3.ModuleMenu.App.refreshMenu"></typo3-immediate-action> <typo3-immediate-action action="TYPO3.Backend.Topbar.refresh"></typo3-immediate-action> </f:if> +</f:section> +<f:section name="Content"> + + <h1> + <f:translate key="LLL:EXT:setup/Resources/Private/Language/locallang.xlf:UserSettings" /> + </h1> <form action="{f:be.uri(route: 'user_setup')}" method="post" @@ -27,10 +31,6 @@ spellcheck="false" > <div id="user-setup-wrapper"> - <h1> - <f:translate key="LLL:EXT:setup/Resources/Private/Language/locallang.xlf:UserSettings" /> - </h1> - <div role="tabpanel"> <ul class="nav nav-tabs t3js-tabs" role="tablist" id="tabs-{menuId}" data-store-last-tab="1"> <f:for each="{menuItems}" as="item" iteration="iteration"> diff --git a/typo3/sysext/tstemplate/Resources/Private/Partials/ActiveConditions.html b/typo3/sysext/tstemplate/Resources/Private/Partials/ActiveConditions.html index b5810c4c1dc2..58350abd4985 100644 --- a/typo3/sysext/tstemplate/Resources/Private/Partials/ActiveConditions.html +++ b/typo3/sysext/tstemplate/Resources/Private/Partials/ActiveConditions.html @@ -61,46 +61,42 @@ > <div class="panel-body"> <form action="{f:be.uri(route: 'typoscript_active', parameters: '{id: pageUid}')}" method="post"> - <div class="row"> - <div class="col-12"> - <f:for each="{conditions}" as="condition"> - <input type="hidden" name="{type}Conditions[{condition.hash}]" value="0" /> - <div class="form-check form-switch"> - <input - type="checkbox" - class="form-check-input" - name="{type}Conditions[{condition.hash}]" - id="{type}Condition{condition.hash}" - value="1" - {f:if(condition: condition.active, then:'checked="checked"')} - data-global-event="change" - data-action-submit="$form" - data-value-selector="input[name='{type}Conditions[{condition.hash}]']" - /> - <label class="form-check-label" for="{type}Condition{condition.hash}"> - <f:if condition="{displayConstantSubstitutions} && {condition.originalValue}"> - <f:then> - <span class="font-monospace">[{condition.value}]</span> - <span class="diff-item-result diff-item-result-inline font-monospace p-0"> - <f:format.raw> - <f:translate - key="LLL:EXT:tstemplate/Resources/Private/Language/locallang_active.xlf:panel.info.conditionWithConstant" - arguments="{ - 0: '{backend:typoScript.fineDiff(from: condition.originalValue, to: condition.value)}' - }" - /> - </f:format.raw> - </span> - </f:then> - <f:else> - <span class="font-monospace">[{condition.value}]</span> - </f:else> - </f:if> - </label> - </div> - </f:for> + <f:for each="{conditions}" as="condition"> + <input type="hidden" name="{type}Conditions[{condition.hash}]" value="0" /> + <div class="form-check form-switch"> + <input + type="checkbox" + class="form-check-input" + name="{type}Conditions[{condition.hash}]" + id="{type}Condition{condition.hash}" + value="1" + {f:if(condition: condition.active, then:'checked="checked"')} + data-global-event="change" + data-action-submit="$form" + data-value-selector="input[name='{type}Conditions[{condition.hash}]']" + /> + <label class="form-check-label" for="{type}Condition{condition.hash}"> + <f:if condition="{displayConstantSubstitutions} && {condition.originalValue}"> + <f:then> + <span class="font-monospace">[{condition.value}]</span> + <span class="diff-item-result diff-item-result-inline font-monospace p-0"> + <f:format.raw> + <f:translate + key="LLL:EXT:tstemplate/Resources/Private/Language/locallang_active.xlf:panel.info.conditionWithConstant" + arguments="{ + 0: '{backend:typoScript.fineDiff(from: condition.originalValue, to: condition.value)}' + }" + /> + </f:format.raw> + </span> + </f:then> + <f:else> + <span class="font-monospace">[{condition.value}]</span> + </f:else> + </f:if> + </label> </div> - </div> + </f:for> </form> </div> </div> diff --git a/typo3/sysext/tstemplate/Resources/Private/Partials/ActiveOptions.html b/typo3/sysext/tstemplate/Resources/Private/Partials/ActiveOptions.html index 17880c69cc02..804544dd0f03 100644 --- a/typo3/sysext/tstemplate/Resources/Private/Partials/ActiveOptions.html +++ b/typo3/sysext/tstemplate/Resources/Private/Partials/ActiveOptions.html @@ -4,9 +4,9 @@ data-namespace-typo3-fluid="true" > -<div class="row row-cols-auto align-items-end g-3 mb-4{f:if(condition: '{f:count(subject: allTemplatesOnPage)} < 2', then: ' pt-2')}"> +<div class="form-row-md"> <f:if condition="{f:count(subject: allTemplatesOnPage)} > 1"> - <div class="col col-12 col-sm-6 col-md-4 col-lg-3 col-xl-2"> + <div class="form-group"> <form action="{f:be.uri(route: 'typoscript_active', parameters: '{id: pageUid}')}" method="post"> <label class="form-label" for="selectedTemplate"> <f:translate key="LLL:EXT:tstemplate/Resources/Private/Language/locallang_active.xlf:options.selectedRecord" /> @@ -31,12 +31,12 @@ </form> </div> </f:if> - <div class="col col-12 col-sm-6 col-md-5 col-lg-4 col-xl-3"> + <div class="form-group"> <form action="#"> <div class="input-group"> <input type="text" - class="form-control t3js-collapse-search-term" + class="form-control form-control-clearable t3js-collapse-search-term" name="searchValue" id="searchValue" data-persist-collapse-search-key="collapse-search-term-typoscript-active" @@ -48,12 +48,12 @@ </div> </form> </div> - <div class="col"> - <div class="row row-cols-md-auto pb-1"> - <div class="col col-12 col-sm-12"> + <div class="form-group"> + <div class="form-row-md"> + <div class="form-group"> <form action="{f:be.uri(route: 'typoscript_active', parameters: '{id: pageUid}')}" method="post"> <input type="hidden" name="displayConstantSubstitutions" value="0" /> - <div class="form-check form-switch"> + <div class="form-check form-switch form-check-size-input"> <input type="checkbox" class="form-check-input" @@ -71,10 +71,10 @@ </div> </form> </div> - <div class="col col-12 col-sm-12"> + <div class="form-group"> <form action="{f:be.uri(route: 'typoscript_active', parameters: '{id: pageUid}')}" method="post"> <input type="hidden" name="displayComments" value="0" /> - <div class="form-check form-switch"> + <div class="form-check form-switch form-check-size-input"> <input type="checkbox" class="form-check-input" @@ -92,10 +92,10 @@ </div> </form> </div> - <div class="col col-12 col-sm-12"> + <div class="form-group"> <form action="{f:be.uri(route: 'typoscript_active', parameters: '{id: pageUid}')}" method="post"> <input type="hidden" name="sortAlphabetically" value="0" /> - <div class="form-check form-switch"> + <div class="form-check form-switch form-check-size-input"> <input type="checkbox" class="form-check-input" diff --git a/typo3/sysext/tstemplate/Resources/Private/Partials/ActiveTreePanel.html b/typo3/sysext/tstemplate/Resources/Private/Partials/ActiveTreePanel.html index f3bc63760aa4..9bf7ad519189 100644 --- a/typo3/sysext/tstemplate/Resources/Private/Partials/ActiveTreePanel.html +++ b/typo3/sysext/tstemplate/Resources/Private/Partials/ActiveTreePanel.html @@ -35,7 +35,7 @@ aria-labelledby="typoscript-active-{type}-ast-heading" role="tabpanel" > - <div class="panel-body t3js-collapse-states-search-tree"> + <div class="panel-body t3js-collapse-states-search-tree"> <form action="{f:be.uri(route: 'typoscript_active', parameters: '{id: pageUid}')}" method="post"> <ul class="treelist"> <f:comment> diff --git a/typo3/sysext/tstemplate/Resources/Private/Partials/AnalyzerConditions.html b/typo3/sysext/tstemplate/Resources/Private/Partials/AnalyzerConditions.html index 6b127e558990..d08969dbdfbf 100644 --- a/typo3/sysext/tstemplate/Resources/Private/Partials/AnalyzerConditions.html +++ b/typo3/sysext/tstemplate/Resources/Private/Partials/AnalyzerConditions.html @@ -61,46 +61,42 @@ > <div class="panel-body"> <form action="{f:be.uri(route: 'web_typoscript_analyzer', parameters: '{id: pageUid}')}" method="post"> - <div class="row"> - <div class="col-12"> - <f:for each="{conditions}" as="condition"> - <input type="hidden" name="{type}Conditions[{condition.hash}]" value="0" /> - <div class="form-check form-switch"> - <input - type="checkbox" - class="form-check-input" - name="{type}Conditions[{condition.hash}]" - id="{type}Condition{condition.hash}" - value="1" - {f:if(condition: condition.active, then:'checked="checked"')} - data-global-event="change" - data-action-submit="$form" - data-value-selector="input[name='{type}Conditions[{condition.hash}]']" - /> - <label class="form-check-label" for="{type}Condition{condition.hash}"> - <f:if condition="{condition.originalValue}"> - <f:then> - <span class="font-monospace">[{condition.value}]</span> - <span class="diff-item-result diff-item-result-inline font-monospace p-0"> - <f:format.raw> - <f:translate - key="LLL:EXT:tstemplate/Resources/Private/Language/locallang_analyzer.xlf:panel.info.conditionWithConstant" - arguments="{ - 0: '{backend:typoScript.fineDiff(from: condition.originalValue, to: condition.value)}' - }" - /> - </f:format.raw> - </span> - </f:then> - <f:else> - <span class="font-monospace">[{condition.value}]</span> - </f:else> - </f:if> - </label> - </div> - </f:for> + <f:for each="{conditions}" as="condition"> + <input type="hidden" name="{type}Conditions[{condition.hash}]" value="0" /> + <div class="form-check form-switch"> + <input + type="checkbox" + class="form-check-input" + name="{type}Conditions[{condition.hash}]" + id="{type}Condition{condition.hash}" + value="1" + {f:if(condition: condition.active, then:'checked="checked"')} + data-global-event="change" + data-action-submit="$form" + data-value-selector="input[name='{type}Conditions[{condition.hash}]']" + /> + <label class="form-check-label" for="{type}Condition{condition.hash}"> + <f:if condition="{condition.originalValue}"> + <f:then> + <span class="font-monospace">[{condition.value}]</span> + <span class="diff-item-result diff-item-result-inline font-monospace p-0"> + <f:format.raw> + <f:translate + key="LLL:EXT:tstemplate/Resources/Private/Language/locallang_analyzer.xlf:panel.info.conditionWithConstant" + arguments="{ + 0: '{backend:typoScript.fineDiff(from: condition.originalValue, to: condition.value)}' + }" + /> + </f:format.raw> + </span> + </f:then> + <f:else> + <span class="font-monospace">[{condition.value}]</span> + </f:else> + </f:if> + </label> </div> - </div> + </f:for> </form> </div> </div> diff --git a/typo3/sysext/tstemplate/Resources/Private/Partials/AnalyzerOptions.html b/typo3/sysext/tstemplate/Resources/Private/Partials/AnalyzerOptions.html index 8fcab05bcba1..1f549fb3232c 100644 --- a/typo3/sysext/tstemplate/Resources/Private/Partials/AnalyzerOptions.html +++ b/typo3/sysext/tstemplate/Resources/Private/Partials/AnalyzerOptions.html @@ -5,8 +5,8 @@ > <f:if condition="{f:count(subject: allTemplatesOnPage)} > 1"> - <div class="row g-3 mb-4"> - <div class="col col-12 col-sm-6 col-md-4 col-lg-3 col-xl-2"> + <div class="form-row"> + <div class="form-group"> <form action="{f:be.uri(route: 'web_typoscript_analyzer', parameters: '{id: pageUid}')}" method="post"> <label class="form-label" for="selectedTemplate"> <f:translate key="LLL:EXT:tstemplate/Resources/Private/Language/locallang_analyzer.xlf:options.selectedRecord" /> diff --git a/typo3/sysext/tstemplate/Resources/Private/Partials/ConstantEditorOptions.html b/typo3/sysext/tstemplate/Resources/Private/Partials/ConstantEditorOptions.html index c0f5c7e85e12..73010d76fd38 100644 --- a/typo3/sysext/tstemplate/Resources/Private/Partials/ConstantEditorOptions.html +++ b/typo3/sysext/tstemplate/Resources/Private/Partials/ConstantEditorOptions.html @@ -5,9 +5,9 @@ > <f:if condition="({f:count(subject: allTemplatesOnPage)} > 1) || ({f:count(subject: relevantCategories)} > 1)"> - <div class="row g-3 mb-4"> + <div class="form-row"> <f:if condition="{f:count(subject: allTemplatesOnPage)} > 1"> - <div class="col col-12 col-sm-6 col-md-4 col-lg-3 col-xl-2"> + <div class="form-group"> <form action="{f:be.uri(route: 'web_typoscript_constanteditor', parameters: '{id: pageUid}')}" method="post"> <label class="form-label" for="selectedTemplate"> <f:translate key="LLL:EXT:tstemplate/Resources/Private/Language/locallang_ceditor.xlf:options.selectedRecord" /> @@ -33,7 +33,7 @@ </div> </f:if> <f:if condition="{f:count(subject: relevantCategories)} > 1"> - <div class="col col-12 col-sm-6 col-md-4 col-lg-3 col-xl-2"> + <div class="form-group"> <form action="{f:be.uri(route: 'web_typoscript_constanteditor', parameters: '{id: pageUid}')}" method="post"> <label class="form-label" for="selectedCategory"> <f:translate key="LLL:EXT:tstemplate/Resources/Private/Language/locallang_ceditor.xlf:options.selectedCategory" /> diff --git a/typo3/sysext/tstemplate/Resources/Private/Templates/ActiveMain.html b/typo3/sysext/tstemplate/Resources/Private/Templates/ActiveMain.html index 5c35829dee9d..92ad7746e884 100644 --- a/typo3/sysext/tstemplate/Resources/Private/Templates/ActiveMain.html +++ b/typo3/sysext/tstemplate/Resources/Private/Templates/ActiveMain.html @@ -5,8 +5,7 @@ <f:layout name="Module"/> -<f:section name="Content"> - +<f:section name="Before"> <f:be.pageRenderer includeJavaScriptModules="{ 0: '@typo3/backend/context-menu.js', @@ -19,11 +18,15 @@ 'collapse-state-search.numberOfSearchMatches': 'LLL:EXT:tstemplate/Resources/Private/Language/locallang_active.xlf:panel.header.numberOfSearchMatches' }" /> - <f:variable name="args" value="{0: 'web', 1: pageUid}" /> - <typo3-immediate-action action="TYPO3.Backend.Storage.ModuleStateStorage.update" args="{args -> f:format.json() -> f:format.htmlspecialchars()}"></typo3-immediate-action> + <typo3-immediate-action + action="TYPO3.Backend.Storage.ModuleStateStorage.update" + args="{args -> f:format.json() -> f:format.htmlspecialchars()}" + ></typo3-immediate-action> +</f:section> + +<f:section name="Content"> - <f:comment><!-- Heading --></f:comment> <h1> <f:if condition="{templateTitle}"> <f:then> diff --git a/typo3/sysext/tstemplate/Resources/Private/Templates/Analyzer.html b/typo3/sysext/tstemplate/Resources/Private/Templates/Analyzer.html index 7aa026d54819..be6510561e2b 100644 --- a/typo3/sysext/tstemplate/Resources/Private/Templates/Analyzer.html +++ b/typo3/sysext/tstemplate/Resources/Private/Templates/Analyzer.html @@ -5,8 +5,7 @@ <f:layout name="Module"/> -<f:section name="Content"> - +<f:section name="Before"> <f:be.pageRenderer includeJavaScriptModules="{ 0: '@typo3/backend/context-menu.js', @@ -14,11 +13,15 @@ 2: '@typo3/tstemplate/template-analyzer.js' }" /> - <f:variable name="args" value="{0: 'web', 1: pageUid}" /> - <typo3-immediate-action action="TYPO3.Backend.Storage.ModuleStateStorage.update" args="{args -> f:format.json() -> f:format.htmlspecialchars()}"></typo3-immediate-action> + <typo3-immediate-action + action="TYPO3.Backend.Storage.ModuleStateStorage.update" + args="{args -> f:format.json() -> f:format.htmlspecialchars()}" + ></typo3-immediate-action> +</f:section> + +<f:section name="Content"> - <f:comment><!-- Heading --></f:comment> <h1> <f:if condition="{templateTitle}"> <f:then> diff --git a/typo3/sysext/tstemplate/Resources/Private/Templates/ConstantEditorMain.html b/typo3/sysext/tstemplate/Resources/Private/Templates/ConstantEditorMain.html index 11e3b6b0d311..c42435a52868 100644 --- a/typo3/sysext/tstemplate/Resources/Private/Templates/ConstantEditorMain.html +++ b/typo3/sysext/tstemplate/Resources/Private/Templates/ConstantEditorMain.html @@ -5,8 +5,7 @@ <f:layout name="Module"/> -<f:section name="Content"> - +<f:section name="Before"> <f:be.pageRenderer includeJavaScriptModules="{ 0: '@typo3/backend/context-menu.js', @@ -15,11 +14,14 @@ 4: '@typo3/tstemplate/constant-editor.js' }" /> - <f:variable name="args" value="{0: 'web', 1: pageUid}" /> - <typo3-immediate-action action="TYPO3.Backend.Storage.ModuleStateStorage.update" args="{args -> f:format.json() -> f:format.htmlspecialchars()}"></typo3-immediate-action> + <typo3-immediate-action + action="TYPO3.Backend.Storage.ModuleStateStorage.update" + args="{args -> f:format.json() -> f:format.htmlspecialchars()}" + ></typo3-immediate-action> +</f:section> - <f:comment><!-- Heading --></f:comment> +<f:section name="Content"> <h1> <f:if condition="{templateTitle}"> <f:then> diff --git a/typo3/sysext/tstemplate/Resources/Private/Templates/InfoModifyMain.html b/typo3/sysext/tstemplate/Resources/Private/Templates/InfoModifyMain.html index b3f8788775a9..c83c6dd02254 100644 --- a/typo3/sysext/tstemplate/Resources/Private/Templates/InfoModifyMain.html +++ b/typo3/sysext/tstemplate/Resources/Private/Templates/InfoModifyMain.html @@ -7,8 +7,7 @@ <f:layout name="Module"/> -<f:section name="Content"> - +<f:section name="Before"> <f:be.pageRenderer includeJavaScriptModules="{ 0: '@typo3/backend/context-menu.js', @@ -16,9 +15,14 @@ 2: '@typo3/tstemplate/information-module.js' }" /> - <f:variable name="args" value="{0: 'web', 1: pageUid}" /> - <typo3-immediate-action action="TYPO3.Backend.Storage.ModuleStateStorage.update" args="{args -> f:format.json() -> f:format.htmlspecialchars()}"></typo3-immediate-action> + <typo3-immediate-action + action="TYPO3.Backend.Storage.ModuleStateStorage.update" + args="{args -> f:format.json() -> f:format.htmlspecialchars()}" + ></typo3-immediate-action> +</f:section> + +<f:section name="Content"> <h1> <f:if condition="{templateRecord.title}"> @@ -38,8 +42,8 @@ <p><f:translate key="LLL:EXT:tstemplate/Resources/Private/Language/locallang_info.xlf:submodule.description" /></p> <f:if condition="{f:count(subject: allTemplatesOnPage)} > 1"> - <div class="row g-3 mb-4"> - <div class="col col-12 col-sm-6 col-md-4 col-lg-3 col-xl-2"> + <div class="form-row"> + <div class="form-group"> <form action="{f:be.uri(route: 'web_typoscript_infomodify', parameters: '{id: pageUid}')}" method="post"> <label class="form-label" for="selectedTemplate"> <f:translate key="LLL:EXT:tstemplate/Resources/Private/Language/locallang_info.xlf:options.selectedRecord" /> diff --git a/typo3/sysext/webhooks/Resources/Private/Templates/Management/Overview.html b/typo3/sysext/webhooks/Resources/Private/Templates/Management/Overview.html index f908debd4e9f..25f53d7f6f68 100644 --- a/typo3/sysext/webhooks/Resources/Private/Templates/Management/Overview.html +++ b/typo3/sysext/webhooks/Resources/Private/Templates/Management/Overview.html @@ -158,12 +158,12 @@ <form action="{f:be.uri(route:'webhooks_management')}" method="post" enctype="multipart/form-data" name="demand"> <input type="hidden" name="orderField" value="{demand.orderField}"> <input type="hidden" name="orderDirection" value="{demand.orderDirection}"> - <div class="row row-cols-auto align-items-end g-3 mb-4"> - <div class="col"> + <div class="form-row"> + <div class="form-group"> <label for="demand-name" class="form-label"><f:translate key="LLL:EXT:webhooks/Resources/Private/Language/locallang_module_webhooks.xlf:filter.name"/></label> <input type="text" id="demand-name" class="form-control" name="demand[name]" value="{demand.name}"/> </div> - <div class="col"> + <div class="form-group"> <label for="demand-webhook-type" class="form-label"><f:translate key="LLL:EXT:webhooks/Resources/Private/Language/locallang_module_webhooks.xlf:filter.webhook_type"/></label> <select id="demand-webhook-type" class="form-select" name="demand[webhook_type]" data-on-change="submit"> <option value=""><f:translate key="LLL:EXT:webhooks/Resources/Private/Language/locallang_module_webhooks.xlf:filter.webhook_type.showAll"/></option> @@ -174,7 +174,7 @@ </f:for> </select> </div> - <div class="col"> + <div class="form-group align-self-end"> <input type="submit" value="{f:translate(key: 'LLL:EXT:webhooks/Resources/Private/Language/locallang_module_webhooks.xlf:filter.sendButton')}" class="btn btn-default" /> <a href="{f:be.uri(route:'webhooks_management')}" class="btn btn-link"><f:translate key="LLL:EXT:webhooks/Resources/Private/Language/locallang_module_webhooks.xlf:filter.resetButton"/></a> </div> diff --git a/typo3/sysext/workspaces/Resources/Private/Partials/WorkingTable.html b/typo3/sysext/workspaces/Resources/Private/Partials/WorkingTable.html index 5ff4b114b880..96658496a3d8 100644 --- a/typo3/sysext/workspaces/Resources/Private/Partials/WorkingTable.html +++ b/typo3/sysext/workspaces/Resources/Private/Partials/WorkingTable.html @@ -5,8 +5,8 @@ > <div class="workspace-panel" id="workspace-panel"> <form id="workspace-settings-form"> - <div class="row row-cols-auto align-items-end g-3 mb-4"> - <div class="col"> + <div class="form-row"> + <div class="form-group"> <label for="depth" class="form-label"><f:translate key="LLL:EXT:workspaces/Resources/Private/Language/locallang.xlf:workingTable.depth" /></label> <select name="depth" id="depth" class="form-select"> <option value="0" {f:if(condition: '{selectedDepth} == 0', then: 'selected')}><f:translate key="LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_0" /></option> @@ -17,7 +17,7 @@ <option value="999" {f:if(condition: '{selectedDepth} == 999', then: 'selected')}><f:translate key="LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_infi" /></option> </select> </div> - <div class="col"> + <div class="form-group"> <label for="languages" class="form-label"><f:translate key="LLL:EXT:workspaces/Resources/Private/Language/locallang.xlf:workingTable.languages" /></label> <div class="input-group"> <span class="input-group-addon input-group-icon"> @@ -30,7 +30,7 @@ </select> </div> </div> - <div class="col"> + <div class="form-group"> <label for="stageFilter" class="form-label"><f:translate key="LLL:EXT:workspaces/Resources/Private/Language/locallang.xlf:workingTable.stages" /></label> <select name="stages" id="stageFilter" class="form-select"> <f:for each="{availableSelectStages}" as="availableSelectStage"> @@ -38,9 +38,9 @@ </f:for> </select> </div> - <div class="col"> + <div class="form-group align-self-end"> <div class="input-group"> - <input class="form-control t3js-clearable" type="text" name="search-text" placeholder="{f:translate(key: 'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.enterSearchString')}"> + <input class="form-control form-control-clearable t3js-clearable" type="text" name="search-text" placeholder="{f:translate(key: 'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.enterSearchString')}"> <button type="submit" class="btn btn-default disabled"><core:icon identifier="actions-search" /></button> </div> </div> -- GitLab