Commit ace65ef4 authored by Benni Mack's avatar Benni Mack
Browse files

[TASK] Re-style record list search box

The search box (accessible via the list module in docheader, and
also used inside the Record Selector) is now simplified by
having a main select field, and additional settings as dropdown
available, making the search box - especially in the record selector -
much more easier to understand and to use. In addition, the record
selector search now looks similar to the File Selector (FAL relations),
as the File Selector uses the same markup now as well.

The doc header in the list module does not jump anymore when
choosing the search box, as this is also now moved into the
main document area, as all other modules (belog etc) use it as well.

The search box component is also extracted from the
DatabaseRecordList class, making it easier to re-use.

As the page module does not have the search anymore,
and thus, would rely on EXT:recordlist to just show the
button, the button (and thus, the jumpyness) is removed
there.

Resolves: #93892
Releases: master
Change-Id: I64259f54a79d0faaeefb45f9528d0a0d0c7b2c59
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/68753

Tested-by: default avatarTYPO3com <noreply@typo3.com>
Tested-by: core-ci's avatarcore-ci <typo3@b13.com>
Tested-by: Oliver Bartsch's avatarOliver Bartsch <bo@cedev.de>
Tested-by: Oliver Hader's avatarOliver Hader <oliver.hader@typo3.org>
Tested-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
Reviewed-by: Oliver Bartsch's avatarOliver Bartsch <bo@cedev.de>
Reviewed-by: Oliver Hader's avatarOliver Hader <oliver.hader@typo3.org>
Reviewed-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
parent 2c0436e5
......@@ -42,11 +42,6 @@ class DocumentHeader {
return;
}
const documentHeaderSearchBar = document.querySelector(this.settings.selectors.moduleSearchBar);
if (documentHeaderSearchBar !== null) {
this.documentHeader.appendChild(documentHeaderSearchBar);
}
const moduleElement = this.documentHeader.parentElement;
new ThrottleEvent('scroll', this.scroll, 100).bindTo(moduleElement);
});
......
......@@ -45,7 +45,6 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Versioning\VersionState;
use TYPO3\CMS\Fluid\View\StandaloneView;
use TYPO3\CMS\Fluid\ViewHelpers\Be\InfoboxViewHelper;
use TYPO3\CMS\Recordlist\RecordList\DatabaseRecordList;
/**
* Script Class for Web > Layout module
......@@ -592,7 +591,6 @@ class PageLayoutController
// All other listings
$content .= $this->renderContent();
$content .= '</form>';
$content .= $this->searchContent;
// Setting up the buttons for the docheader
$this->makeButtons($request);
......@@ -694,17 +692,7 @@ class PageLayoutController
$content .= GeneralUtility::callUserFunction($hook, $params, $this);
}
$content .= $tableOutput;
// Making search form:
$this->searchContent = $this->getSearchBox();
if ($this->searchContent) {
$this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/ToggleSearchToolbox');
$toggleSearchFormButton = $this->buttonBar->makeLinkButton()
->setClasses('t3js-toggle-search-toolbox')
->setTitle($this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.title.searchIcon'))
->setIcon($this->iconFactory->getIcon('actions-search', Icon::SIZE_SMALL))
->setHref('#');
$this->buttonBar->addButton($toggleSearchFormButton, ButtonBar::BUTTON_POSITION_LEFT, 4);
}
// Additional footer content
foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/db_layout.php']['drawFooterHook'] ?? [] as $hook) {
$params = [];
......@@ -1036,24 +1024,6 @@ class PageLayoutController
return !(bool)($targetPage['hidden'] ?? false) ? $targetPage : [];
}
/**
* Creates the search box
*
* @return string HTML for the search box
*/
protected function getSearchBox(): string
{
if (!$this->getBackendUser()->check('modules', 'web_list')) {
return '';
}
$dbList = GeneralUtility::makeInstance(DatabaseRecordList::class);
$dbList->start($this->id, '', '');
$formUrl = $this->uriBuilder->buildUriFromRoute('web_list', ['id' => $this->id]);
return '<div class="module-docheader-bar t3js-module-docheader-bar t3js-module-docheader-bar-search" id="db_list-searchbox-toolbar" style="display: none;"><div class="panel panel-default"><div class="p-2 ps-4">' . $dbList->getSearchBox((string)$formUrl) . '</div></div></div>';
}
/**
* Returns the shortcut title for the current page
*
......
......@@ -10,4 +10,4 @@
*
* The TYPO3 project - inspiring people to share!
*/
define(["require","exports","TYPO3/CMS/Core/DocumentService","TYPO3/CMS/Core/Event/ThrottleEvent"],(function(t,e,i,o){"use strict";return new class{constructor(){this.documentHeader=null,this.direction="down",this.reactionRange=300,this.lastPosition=0,this.currentPosition=0,this.changedPosition=0,this.settings={margin:24,offset:100,selectors:{moduleDocumentHeader:".t3js-module-docheader",moduleSearchBar:".t3js-module-docheader-bar-search"}},this.scroll=t=>{this.currentPosition=t.target.scrollTop,this.currentPosition>this.lastPosition?"down"!==this.direction&&(this.direction="down",this.changedPosition=this.currentPosition):this.currentPosition<this.lastPosition&&"up"!==this.direction&&(this.direction="up",this.changedPosition=this.currentPosition),"up"===this.direction&&this.changedPosition-this.reactionRange<this.currentPosition&&this.documentHeader.classList.remove("module-docheader-folded"),"down"===this.direction&&this.changedPosition+this.reactionRange<this.currentPosition&&this.documentHeader.classList.add("module-docheader-folded"),this.lastPosition=this.currentPosition},i.ready().then(()=>{if(this.documentHeader=document.querySelector(this.settings.selectors.moduleDocumentHeader),null===this.documentHeader)return;const t=document.querySelector(this.settings.selectors.moduleSearchBar);null!==t&&this.documentHeader.appendChild(t);const e=this.documentHeader.parentElement;new o("scroll",this.scroll,100).bindTo(e)})}}}));
\ No newline at end of file
define(["require","exports","TYPO3/CMS/Core/DocumentService","TYPO3/CMS/Core/Event/ThrottleEvent"],(function(t,e,i,o){"use strict";return new class{constructor(){this.documentHeader=null,this.direction="down",this.reactionRange=300,this.lastPosition=0,this.currentPosition=0,this.changedPosition=0,this.settings={margin:24,offset:100,selectors:{moduleDocumentHeader:".t3js-module-docheader",moduleSearchBar:".t3js-module-docheader-bar-search"}},this.scroll=t=>{this.currentPosition=t.target.scrollTop,this.currentPosition>this.lastPosition?"down"!==this.direction&&(this.direction="down",this.changedPosition=this.currentPosition):this.currentPosition<this.lastPosition&&"up"!==this.direction&&(this.direction="up",this.changedPosition=this.currentPosition),"up"===this.direction&&this.changedPosition-this.reactionRange<this.currentPosition&&this.documentHeader.classList.remove("module-docheader-folded"),"down"===this.direction&&this.changedPosition+this.reactionRange<this.currentPosition&&this.documentHeader.classList.add("module-docheader-folded"),this.lastPosition=this.currentPosition},i.ready().then(()=>{if(this.documentHeader=document.querySelector(this.settings.selectors.moduleDocumentHeader),null===this.documentHeader)return;const t=this.documentHeader.parentElement;new o("scroll",this.scroll,100).bindTo(t)})}}}));
\ No newline at end of file
......@@ -23,6 +23,7 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\MathUtility;
use TYPO3\CMS\Recordlist\Tree\View\ElementBrowserPageTreeView;
use TYPO3\CMS\Recordlist\Tree\View\LinkParameterProviderInterface;
use TYPO3\CMS\Recordlist\View\RecordSearchBoxComponent;
/**
* Showing a page tree and allows you to browse for records
......@@ -38,6 +39,7 @@ class DatabaseBrowser extends AbstractElementBrowser implements ElementBrowserIn
* @var int|null
*/
protected $expandPage;
protected array $modTSconfig = [];
protected function initialize()
{
......@@ -75,6 +77,7 @@ class DatabaseBrowser extends AbstractElementBrowser implements ElementBrowserIn
public function render()
{
$userTsConfig = $this->getBackendUser()->getTSConfig();
$this->modTSconfig = BackendUtility::getPagesTSconfig((int)$this->expandPage)['mod.']['web_list.'] ?? [];
$this->setTemporaryDbMounts();
[, , , $allowedTables] = explode('|', $this->bparams);
......@@ -217,18 +220,21 @@ class DatabaseBrowser extends AbstractElementBrowser implements ElementBrowserIn
$dbList->setRelatingTableAndField($relatingTableName, $relatingFieldName);
}
$selectedTable = GeneralUtility::_GP('table');
$searchWord = (string)GeneralUtility::_GP('search_field');
$searchLevels = (int)GeneralUtility::_GP('search_levels');
$dbList->start(
$this->expandPage,
GeneralUtility::_GP('table'),
$selectedTable,
MathUtility::forceIntegerInRange(GeneralUtility::_GP('pointer'), 0, 100000),
GeneralUtility::_GP('search_field'),
GeneralUtility::_GP('search_levels')
$searchWord,
$searchLevels
);
$dbList->setDispFields();
$tableList = $dbList->generateList();
$out .= '<div class="p-2 pb-3 border">' . $dbList->getSearchBox() . '</div>';
$out .= $this->renderSearchBox($dbList, $searchWord, $searchLevels);
// Add the HTML for the record list to output variable:
$out .= $tableList;
......@@ -242,6 +248,16 @@ class DatabaseBrowser extends AbstractElementBrowser implements ElementBrowserIn
return $out;
}
protected function renderSearchBox(ElementBrowserRecordList $dblist, string $searchWord, int $searchLevels): string
{
$searchBox = GeneralUtility::makeInstance(RecordSearchBoxComponent::class)
->setAllowedSearchLevels((array)($this->modTSconfig['searchLevel.']['items.'] ?? []))
->setSearchWord($searchWord)
->setSearchLevel($searchLevels)
->render($dblist->listURL('', '-1', 'pointer,search_field'));
return '<div class="pt-2">' . $searchBox . '</div>';
}
/**
* @return string[] Array of body-tag attributes
*/
......
......@@ -32,6 +32,7 @@ use TYPO3\CMS\Core\Utility\MathUtility;
use TYPO3\CMS\Core\Utility\PathUtility;
use TYPO3\CMS\Recordlist\Tree\View\LinkParameterProviderInterface;
use TYPO3\CMS\Recordlist\View\FolderUtilityRenderer;
use TYPO3\CMS\Recordlist\View\RecordSearchBoxComponent;
/**
* Browser for files
......@@ -95,7 +96,7 @@ class FileBrowser extends AbstractElementBrowser implements ElementBrowserInterf
{
parent::initVariables();
$this->expandFolder = $this->getRequest()->getParsedBody()['expandFolder'] ?? $this->getRequest()->getQueryParams()['expandFolder'] ?? null;
$this->searchWord = $this->getRequest()->getParsedBody()['searchWord'] ?? $this->getRequest()->getQueryParams()['searchWord'] ?? '';
$this->searchWord = $this->getRequest()->getParsedBody()['search_field'] ?? $this->getRequest()->getQueryParams()['search_field'] ?? '';
}
/**
......@@ -320,8 +321,13 @@ class FileBrowser extends AbstractElementBrowser implements ElementBrowserInterf
}
}
$formUrl = $this->getScriptUrl() . HttpUtility::buildQueryString($this->getUrlParameters([]), '&');
$searchBox = GeneralUtility::makeInstance(RecordSearchBoxComponent::class)
->setSearchWord($this->searchWord)
->render($formUrl);
$markup = [];
$markup[] = GeneralUtility::makeInstance(FolderUtilityRenderer::class, $this)->getFileSearchField($this->searchWord);
$markup[] = '<div class="pt-2 pb-3">' . $searchBox . '</div>';
$markup[] = '<div id="filelist">';
$markup[] = ' ' . $this->getBulkSelector();
$markup[] = ' <table class="table table-sm table-responsive table-striped table-hover" id="typo3-filelist">';
......
......@@ -45,6 +45,7 @@ use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Recordlist\Event\RenderAdditionalContentToRecordListEvent;
use TYPO3\CMS\Recordlist\RecordList\DatabaseRecordList;
use TYPO3\CMS\Recordlist\View\RecordSearchBoxComponent;
/**
* Script Class for the Web > List module; rendering the listing of records on a page
......@@ -260,11 +261,12 @@ class RecordListController
$body .= $additionalRecordListEvent->getAdditionalContentAbove();
$this->moduleTemplate->setTitle($title);
$beforeOutput = '';
$output = '';
// Show the selector to add page translations and the list of translations of the current page
// but only when in "default" mode
if ($this->id && !$dblist->csvOutput && !$search_field && !$cmd && !$table) {
$output .= $this->languageSelector($request->getAttribute('normalizedParams')->getRequestUri());
$beforeOutput .= $this->languageSelector($request->getAttribute('normalizedParams')->getRequestUri());
$pageTranslationsDatabaseRecordList = clone $dblist;
$pageTranslationsDatabaseRecordList->listOnlyInSingleTableMode = false;
$pageTranslationsDatabaseRecordList->disableSingleTableView = true;
......@@ -275,6 +277,11 @@ class RecordListController
$output .= $pageTranslationsDatabaseRecordList->getTable('pages', $this->id);
}
// search box toolbar
if (!($this->modTSconfig['disableSearchBox'] ?? false) && ($tableOutput || !empty($search_field))) {
$beforeOutput .= $this->renderSearchBox($dblist, $search_field, $search_levels);
}
if (!empty($tableOutput)) {
$output .= $tableOutput;
} else {
......@@ -301,6 +308,9 @@ class RecordListController
$defaultFlashMessageQueue->enqueue($flashMessage);
}
if ($beforeOutput) {
$body .= '<div class="row">' . $beforeOutput . '</div>';
}
$body .= '<form action="' . htmlspecialchars($dblist->listURL()) . '" method="post" name="dblistForm">';
$body .= $output;
$body .= '<input type="hidden" name="cmd_table" /><input type="hidden" name="cmd" /></form>';
......@@ -357,34 +367,12 @@ class RecordListController
$dblist->listURL(),
$MOD_SETTINGS
);
// search box toolbar
$content = '';
if (!($this->modTSconfig['disableSearchBox'] ?? false) && ($tableOutput || !empty($dblist->searchString))) {
$searchBoxVisible = !empty($dblist->searchString);
$searchBox = $dblist->getSearchBox();
$content .= '<div class="module-docheader-bar mb-0 t3js-module-docheader-bar-search" id="db_list-searchbox-toolbar" style="' . ($searchBoxVisible ? 'display: block;' : 'display: none;') . '"><div class="panel panel-default"><div class="p-2 ps-4">' . $searchBox . '</div></div></div>';
$this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/ToggleSearchToolbox');
$searchButton = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar()->makeLinkButton();
$searchButton
->setHref('#')
->setClasses('t3js-toggle-search-toolbox')
->setTitle($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.title.searchIcon'))
->setIcon($this->iconFactory->getIcon('actions-search', Icon::SIZE_SMALL));
$this->moduleTemplate->getDocHeaderComponent()->getButtonBar()->addButton(
$searchButton,
ButtonBar::BUTTON_POSITION_LEFT,
90
);
}
if ($pageinfo) {
$this->moduleTemplate->getDocHeaderComponent()->setMetaInformation($pageinfo);
}
// Build the <body> for the module
$content .= $body;
$this->moduleTemplate->setContent($content);
$this->moduleTemplate->setContent($body);
return new HtmlResponse($this->moduleTemplate->renderContent());
}
......@@ -424,6 +412,31 @@ class RecordListController
return $clipboard;
}
protected function renderSearchBox(DatabaseRecordList $dblist, string $searchWord, int $searchLevels): string
{
$searchBoxVisible = !empty($dblist->searchString);
$searchBox = GeneralUtility::makeInstance(RecordSearchBoxComponent::class)
->setAllowedSearchLevels((array)($this->modTSconfig['searchLevel.']['items.'] ?? []))
->setSearchWord($searchWord)
->setSearchLevel($searchLevels)
->render($dblist->listURL('', '-1', 'pointer,search_field'));
$this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/ToggleSearchToolbox');
$buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar();
$searchButton = $buttonBar->makeLinkButton();
$searchButton
->setHref('#')
->setClasses('t3js-toggle-search-toolbox')
->setTitle($this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.title.searchIcon'))
->setIcon($this->iconFactory->getIcon('actions-search', Icon::SIZE_SMALL));
$buttonBar->addButton(
$searchButton,
ButtonBar::BUTTON_POSITION_LEFT,
90
);
return '<div class="col-6" style="' . ($searchBoxVisible ?: 'display: none') . '" id="db_list-searchbox-toolbar">' . $searchBox . '</div>';
}
/**
* Create the panel of buttons for submitting the form or otherwise perform
* operations.
......@@ -641,11 +654,10 @@ class RecordListController
$output .= '<option value="' . htmlspecialchars($targetUrl) . '">' . htmlspecialchars($languageTitle) . '</option>';
}
return '<div class="form-inline form-inline-spaced">'
. '<div class="form-group">'
return '<div class="col-auto">'
. '<select class="form-select" name="createNewLanguage" data-global-event="change" data-action-navigate="$value">'
. $output
. '</select></div></div>';
. '</select></div>';
}
return '';
}
......
......@@ -2380,23 +2380,6 @@ class DatabaseRecordList
return array_keys($orderedTableNames);
}
/**
* Creates the search box
*
* @return string HTML for the search box
*/
public function getSearchBox(string $formUrl = null): string
{
return $this->getFluidTemplateObject('Search.html')
->assignMultiple([
'formUrl' => $formUrl ?? $this->listURL('', '-1', 'pointer,search_field'),
'searchLevelsFromTSconfig' => (array)(BackendUtility::getPagesTSconfig($this->id)['mod.']['web_list.']['searchLevel.']['items.'] ?? []),
'selectedSearchLevel' => $this->searchLevels,
'searchString' => $this->searchString
])
->render();
}
/**
* Setting the field names to display in extended list.
* Sets the internal variable $this->setFields
......
......@@ -17,8 +17,6 @@ namespace TYPO3\CMS\Recordlist\View;
use TYPO3\CMS\Backend\Routing\UriBuilder;
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
use TYPO3\CMS\Core\Imaging\Icon;
use TYPO3\CMS\Core\Imaging\IconFactory;
use TYPO3\CMS\Core\Localization\LanguageService;
use TYPO3\CMS\Core\Resource\Folder;
use TYPO3\CMS\Core\Resource\OnlineMedia\Helpers\OnlineMediaHelperRegistry;
......@@ -38,7 +36,6 @@ class FolderUtilityRenderer
*/
protected $parameterProvider;
protected UriBuilder $uriBuilder;
protected IconFactory $iconFactory;
/**
* @param LinkParameterProviderInterface $parameterProvider
......@@ -47,7 +44,6 @@ class FolderUtilityRenderer
{
$this->parameterProvider = $parameterProvider;
$this->uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
$this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
}
/**
......@@ -227,31 +223,6 @@ class FolderUtilityRenderer
return $code;
}
/**
* Get the HTML data required for the file search field of the TYPO3 Element Browser.
*
* @param string $searchWord
* @return string HTML data required for the search field in the file list of the Element Browser
*/
public function getFileSearchField(string $searchWord): string
{
$action = $this->parameterProvider->getScriptUrl()
. HttpUtility::buildQueryString($this->parameterProvider->getUrlParameters([]), '&');
$markup = [];
$markup[] = '<form method="post" action="' . htmlspecialchars($action) . '" class="pt-2 pb-3">';
$markup[] = ' <div class="input-group">';
$markup[] = ' <span class="input-group-text">';
$markup[] = $this->iconFactory->getIcon('actions-search', Icon::SIZE_SMALL)->render();
$markup[] = ' </span>';
$markup[] = ' <input class="form-control" type="search" name="searchWord" value="' . htmlspecialchars($searchWord) . '" placeholder="' . htmlspecialchars(
$this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:search')
) . '">';
$markup[] = ' </div>';
$markup[] = '</form>';
return implode(LF, $markup);
}
protected function getLanguageService(): LanguageService
{
return $GLOBALS['LANG'];
......
<?php
declare(strict_types=1);
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
namespace TYPO3\CMS\Recordlist\View;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Fluid\View\StandaloneView;
use TYPO3Fluid\Fluid\View\ViewInterface;
/**
* Renders the search box for the record listing and the element browser.
*
* @internal
*/
class RecordSearchBoxComponent
{
protected ViewInterface $view;
protected array $allowedSearchLevels = [];
protected string $searchWord = '';
protected int $searchLevel = 0;
public function __construct(ViewInterface $view = null)
{
$this->view = $view ?? $this->getView('Search.html');
}
public function setSearchWord(string $searchWord): self
{
$this->searchWord = $searchWord;
return $this;
}
public function setSearchLevel(int $searchLevel): self
{
$this->searchLevel = $searchLevel;
return $this;
}
public function setAllowedSearchLevels(array $allowedSearchLevels): self
{
$this->allowedSearchLevels = $allowedSearchLevels;
return $this;
}
public function render(string $formUrl = ''): string
{
return $this->view
->assignMultiple([
'formUrl' => $formUrl,
'availableSearchLevels' => $this->allowedSearchLevels,
'selectedSearchLevel' => $this->searchLevel,
'searchString' => $this->searchWord
])
->render();
}
protected function getView(string $filename): StandaloneView
{
$view = GeneralUtility::makeInstance(StandaloneView::class);
$view->setTemplateRootPaths(['EXT:recordlist/Resources/Private/Templates']);
$view->setTemplate($filename);
return $view;
}
}
<form action="{formUrl}" method="post" id="typo3-dblist-search">
<div class="container-fluid p-0">
<div class="row align-items-end">
<div class="col-sm-6 col-12">
<label for="search_field">
<f:translate id="LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.label.searchString"/>
</label>
<input class="form-control" type="search" placeholder="{f:translate(id:'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.enterSearchString')}" title="{f:translate(id: 'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.title.searchString')}" name="search_field" id="search_field" value="{searchString}" />
<form action="{formUrl}" method="post">
<div class="input-group">
<button class="btn btn-default" type="submit" name="search">
<core:icon identifier="actions-search" size="small" />
</button>
<label for="search_field" class="visually-hidden">
<f:translate id="LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.label.searchString"/>
</label>
<input class="form-control" type="search" placeholder="{f:translate(id:'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.enterSearchString')}" title="{f:translate(id: 'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.title.searchString')}" name="search_field" id="search_field" value="{searchString}" />
<f:if condition="{availableSearchLevels -> f:count()} > 0">
<button class="btn btn-default dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false"></button>
<div class="dropdown-menu">
<div class="row g-3">
<div class="col-12">
<label for="search_levels"><f:translate id="LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.label.search_levels" /></label>
<select class="form-select" name="search_levels" title="{f:translate(id: 'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.title.search_levels')}" id="search_levels">
<f:for each="{availableSearchLevels}" as="searchLevel" key="level">
<option {f:if(condition: '{level} == {selectedSearchLevel}', then: ' selected="selected"')} value="{level}">
<f:translate id="LLL:{searchLevel}">{searchLevel}</f:translate>
</option>
</f:for>
</select>
</div>
<div class="col-12">
<button type="submit" class="float-end btn btn-default" name="searchSubmit" title="{f:translate(id:'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.title.search')}">
<core:icon identifier="actions-search" />
<f:translate id="LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.search"/>
</button>
</div>
</div>
</div>
<div class="col-12 col-sm-3">
<label for="search_levels"><f:translate id="LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.label.search_levels" /></label>
<select class="form-select" name="search_levels" title="{f:translate(id: 'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.title.search_levels')}" id="search_levels">
<f:for each="{searchLevelsFromTSconfig}" as="searchLevelFromTsConfig" key="level">
<option {f:if(condition: '{level} == {selectedSearchLevel}', then: ' selected="selected"')} value="{level}">
<f:translate id="LLL:{searchLevelFromTsConfig}">{searchLevelFromTsConfig}</f:translate>
</option>
</f:for>
</select>
</div>
<div class="col-12 col-sm-3">
<label class="form-label">&nbsp;</label>
<button type="submit" class="btn btn-default" name="search" title="{f:translate(id:'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.title.search')}">
<core:icon identifier="actions-search" />
<f:translate id="LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.search"/>
</button>
</div>
</div>
</f:if>
</div>
</form>
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment