Commit ceebe9b6 authored by Benni Mack's avatar Benni Mack Committed by Andreas Fernandez
Browse files

[FEATURE] Use dropdown for secondary action items

This change replaces the "collapse-horizontal" functionality
of the extended view icons into a dropdown from Bootstrap,
allowing users to understand the icons better because the
text is now also written next to the icon (similar to
the Context Menu).

The horizontal collapsing is removed as a UX improvement
to
a) give consistency around other areas in TYPO3 Backend
b) was intended as a workaround to solve the Extended View rendering and to avoid button-hell
c) avoid confusion around editors when buttons are visually moving horizontally
d) the Extended View feature was unclear for editors when to enable it

In addition the "View" link is now moved into the secondary button group.

The Extended View checkbox is therefore removed as all secondary
options are always available.

Same functionality is also replaced in the File List module to use
the "..." icon to show that there are more actions available.

Side note: The dropdown needs a position-static due to
overflow-x: auto - see https://github.com/twbs/bootstrap/issues/29313#issuecomment-758412385

Resolves: #94390
Releases: master
Change-Id: I925aa7690068fbde3f3aa5217f3f5629a2a890d1
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/67458

Tested-by: core-ci's avatarcore-ci <typo3@b13.com>
Tested-by: Oliver Bartsch's avatarOliver Bartsch <bo@cedev.de>
Tested-by: Andreas Fernandez's avatarAndreas Fernandez <a.fernandez@scripting-base.de>
Reviewed-by: Oliver Bartsch's avatarOliver Bartsch <bo@cedev.de>
Reviewed-by: Andreas Fernandez's avatarAndreas Fernandez <a.fernandez@scripting-base.de>
parent c9e6a55f
......@@ -115,24 +115,6 @@ $panel-lg-padding: 35px;
}
}
.recordlist {
.table-fit {
margin-bottom: 0;
}
// 'panel-heading' is replaced with '.card-header' in twbs4
.card-header,
.panel-heading {
padding: 0.625rem 1rem;
> a,
> span {
padding: 4px 0;
display: inline-block;
}
}
}
//
// Panel hover
//
......
......@@ -17,3 +17,15 @@
font-size: 14px;
}
}
.dropdown-toggle-no-chevron:after {
display: none;
}
.dropdown-list .dropdown-item {
.icon {
margin-right: 0.5rem;
}
padding: 0.375rem 1rem 0.375rem 0.75rem;
}
......@@ -5,6 +5,18 @@
.recordlist {
overflow: unset;
.recordlist-heading {
font-weight: 700;
background-color: #d7d7d7;
padding: 0.625rem 1rem;
> a,
> span {
padding: 4px 0;
display: inline-block;
}
}
table tr {
td.deletePlaceholder {
text-decoration: line-through;
......
......@@ -92,7 +92,7 @@ class Filelist {
new RegularEvent('click', (event: Event, target: HTMLElement): void => {
event.preventDefault();
Filelist.openInfoPopup('_FILE', target.dataset.identifier);
}).delegateTo(document, 'a.btn.filelist-file-info');
}).delegateTo(document, 'a.filelist-file-info');
new RegularEvent('click', (event: Event, target: HTMLElement): void => {
event.preventDefault();
......@@ -106,7 +106,7 @@ class Filelist {
? encodeURIComponent(url)
: encodeURIComponent(top.list_frame.document.location.pathname + top.list_frame.document.location.search);
top.list_frame.location.href = url + '&redirect=' + redirectUrl;
}).delegateTo(document, 'a.btn.filelist-file-copy');
}).delegateTo(document, 'a.filelist-file-copy');
// clipboard events
const clipboardCmd = document.querySelector('[data-event-name="filelist:clipboard:cmd"]');
......
......@@ -1193,7 +1193,6 @@ return [
'checkStoredRecords' => true,
'checkStoredRecordsLoose' => true,
'defaultUserTSconfig' => 'options.enableBookmarks=1
options.file_list.enableDisplayBigControlPanel=selectable
options.file_list.enableDisplayThumbnails=selectable
options.file_list.enableClipBoard=selectable
options.file_list.thumbnail {
......@@ -1223,7 +1222,6 @@ return [
',
// String (exclude). Enter lines of default backend user/group TSconfig.
'defaultPageTSconfig' => '
mod.web_list.enableDisplayBigControlPanel=selectable
mod.web_list.enableClipBoard=selectable
mod.web_list.tableDisplayOrder {
be_users.after = be_groups
......
.. include:: ../../Includes.txt
==================================================================================
Feature: #94390 - Dropdown for record list and file list in favor of Extended View
==================================================================================
See :issue:`94390`
Description
===========
The option "Extended View", which was used in the TYPO3 Backend
modules "Web => List" and "File => Filelist" to show additional icons,
has been removed in favor of a dropdown with all items which is
always available.
Impact
======
This change is added as a UX Improvement over an additional
configuration option to give editors a unified experience, as
the additional menu with alternative items is common in other
web applications.
The TSconfig options `options.file_list.enableDisplayBigControlPanel`
and `mod.web_list.enableDisplayBigControlPanel` have no effect anymore,
because the checkboxes are removed.
.. index:: Backend, ext:backend
\ No newline at end of file
......@@ -275,7 +275,6 @@ class FileListController extends ActionController implements LoggerAwareInterfac
'reverse' => '',
'displayThumbs' => '',
'clipBoard' => '',
'bigControlPanel' => ''
];
// CLEANSE SETTINGS
$this->MOD_SETTINGS = BackendUtility::getModuleData(
......@@ -312,14 +311,8 @@ class FileListController extends ActionController implements LoggerAwareInterfac
protected function initializeIndexAction()
{
// Apply predefined values for hidden checkboxes
// Set predefined value for DisplayBigControlPanel:
$backendUser = $this->getBackendUser();
$userTsConfig = $backendUser->getTSConfig();
if (($userTsConfig['options.']['file_list.']['enableDisplayBigControlPanel'] ?? '') === 'activated') {
$this->MOD_SETTINGS['bigControlPanel'] = true;
} elseif (($userTsConfig['options.']['file_list.']['enableDisplayBigControlPanel'] ?? '') === 'deactivated') {
$this->MOD_SETTINGS['bigControlPanel'] = false;
}
// Set predefined value for DisplayThumbnails:
if (($userTsConfig['options.']['file_list.']['enableDisplayThumbnails'] ?? '') === 'activated') {
$this->MOD_SETTINGS['displayThumbs'] = true;
......@@ -393,8 +386,7 @@ class FileListController extends ActionController implements LoggerAwareInterfac
MathUtility::forceIntegerInRange($this->pointer, 0, 100000),
$this->MOD_SETTINGS['sort'],
(bool)($this->MOD_SETTINGS['reverse'] ?? false),
(bool)($this->MOD_SETTINGS['clipBoard'] ?? false),
(bool)($this->MOD_SETTINGS['bigControlPanel'] ?? false)
(bool)($this->MOD_SETTINGS['clipBoard'] ?? false)
);
// Generate the list, if accessible
if ($this->folderObject->getStorage()->isBrowsable()) {
......@@ -435,18 +427,6 @@ class FileListController extends ActionController implements LoggerAwareInterfac
$this->view->assign('headline', $this->getModuleHeadline());
$this->view->assign('checkboxes', [
'bigControlPanel' => [
'enabled' => ($userTsConfig['options.']['file_list.']['enableDisplayBigControlPanel'] ?? '') === 'selectable',
'label' => htmlspecialchars($this->getLanguageService()->getLL('bigControlPanel')),
'html' => BackendUtility::getFuncCheck(
$this->id,
'SET[bigControlPanel]',
$this->MOD_SETTINGS['bigControlPanel'] ?? '',
'',
'',
'id="bigControlPanel"'
),
],
'displayThumbs' => [
'enabled' => $GLOBALS['TYPO3_CONF_VARS']['GFX']['thumbnails'] && ($userTsConfig['options.']['file_list.']['enableDisplayThumbnails'] ?? '') === 'selectable',
'label' => htmlspecialchars($this->getLanguageService()->getLL('displayThumbs')),
......@@ -783,18 +763,6 @@ class FileListController extends ActionController implements LoggerAwareInterfac
$addParams .= '&tx_filelist_file_filelistlist%5BsearchWord%5D=' . htmlspecialchars($searchWord);
}
$this->view->assign('checkboxes', [
'bigControlPanel' => [
'enabled' => $userTsConfig['options.']['file_list.']['enableDisplayBigControlPanel'] === 'selectable',
'label' => htmlspecialchars($this->getLanguageService()->getLL('bigControlPanel')),
'html' => BackendUtility::getFuncCheck(
$this->id,
'SET[bigControlPanel]',
$this->MOD_SETTINGS['bigControlPanel'] ?? '',
'',
$addParams,
'id="bigControlPanel"'
),
],
'displayThumbs' => [
'enabled' => $GLOBALS['TYPO3_CONF_VARS']['GFX']['thumbnails'] && $userTsConfig['options.']['file_list.']['enableDisplayThumbnails'] === 'selectable',
'label' => htmlspecialchars($this->getLanguageService()->getLL('displayThumbs')),
......
......@@ -212,9 +212,8 @@ class FileList
* @param string $sort Sorting column
* @param bool $sortRev Sorting direction
* @param bool $clipBoard
* @param bool $bigControlPanel Show clipboard flag
*/
public function start(Folder $folderObject, $pointer, $sort, $sortRev, $clipBoard = false, $bigControlPanel = false)
public function start(Folder $folderObject, $pointer, $sort, $sortRev, $clipBoard = false)
{
$this->folderObject = $folderObject;
$this->counter = 0;
......@@ -223,12 +222,9 @@ class FileList
$this->sortRev = $sortRev;
$this->firstElementNumber = $pointer;
// Cleaning rowlist for duplicates and place the $titleCol as the first column always!
$rowlist = 'file,_LOCALIZATION_,fileext,tstamp,size,rw,_REF_';
$rowlist = 'file,_LOCALIZATION_,_CONTROL_,fileext,tstamp,size,rw,_REF_';
if ($clipBoard) {
$rowlist = str_replace('_LOCALIZATION_,', '_LOCALIZATION_,_CLIPBOARD_,', $rowlist);
}
if ($bigControlPanel) {
$rowlist = str_replace('_LOCALIZATION_,', '_LOCALIZATION_,_CONTROL_,', $rowlist);
$rowlist = str_replace('_CONTROL_,', '_CONTROL_,_CLIPBOARD_,', $rowlist);
}
$this->fieldArray = explode(',', $rowlist);
}
......@@ -343,8 +339,8 @@ class FileList
}
return '
<div class="panel panel-default">
<div class="table-fit">
<div class="mb-4 mt-4">
<div class="table-fit mb-0">
<table class="table table-striped table-hover" id="typo3-filelist">
<thead>' . $this->addElement('', $theData, 'th') . '</thead>
<tbody>' . $iOut . '</tbody>
......@@ -1133,8 +1129,36 @@ class FileList
$hookObject->manipulateEditIcons($cells, $this);
}
unset($cells['__fileOrFolderObject']);
// Compile items into a DIV-element:
return '<div class="btn-group">' . implode('', $cells) . '</div>';
// Compile items into a dropdown
$cellOutput = '';
$output = '';
foreach ($cells as $key => $action) {
if (in_array($key, ['view', 'metadata', 'delete'])) {
$output .= $action;
continue;
}
if ($action === $this->spaceIcon) {
continue;
}
// This is a backwards-compat layer for the existing hook items, which will be removed in TYPO3 v12.
$action = str_replace('btn btn-default', 'dropdown-item', $action);
$title = [];
preg_match('/title="([^"]*)"/', $action, $title);
if (empty($title)) {
preg_match('/aria-label="([^"]*)"/', $action, $title);
}
if (!empty($title[1] ?? '')) {
$action = str_replace('</a>', ' ' . $title[1] . '</a>', $action);
$action = str_replace('</button>', ' ' . $title[1] . '</button>', $action);
}
$cellOutput .= '<li>' . $action . '</li>';
}
$icon = $this->iconFactory->getIcon('actions-menu-alternative', Icon::SIZE_SMALL);
$output .= '<div class="btn-group dropdown position-static">' .
'<a href="#actions_' . $fileOrFolderObject->getHashedIdentifier() . '" class="btn btn-default dropdown-toggle dropdown-toggle-no-chevron" data-bs-toggle="dropdown" data-bs-boundary="window" aria-expanded="false">' . $icon->render() . '</a>' .
'<ul id="actions_' . $fileOrFolderObject->getHashedIdentifier() . '" class="dropdown-menu dropdown-list">' . $cellOutput . '</ul>' .
'</div>';
return '<div class="btn-group position-static">' . $output . '</div>';
}
/**
......
......@@ -3,9 +3,6 @@
<file source-language="en" datatype="plaintext" original="EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf" date="2011-10-17T20:22:34Z" product-name="lang">
<header/>
<body>
<trans-unit id="bigControlPanel" resname="bigControlPanel">
<source>Extended view</source>
</trans-unit>
<trans-unit id="clipBoard" resname="clipBoard">
<source>Show clipboard</source>
</trans-unit>
......
......@@ -2,14 +2,6 @@
Listing options for extended view, clipboard and thumbnails
-->
<div class="typo3-listOptions">
<f:if condition="{checkboxes.bigControlPanel.enabled}">
<div class="form-check">
{checkboxes.bigControlPanel.html -> f:format.raw()}
<label for="bigControlPanel" class="form-check-label">
{checkboxes.bigControlPanel.label}
</label>
</div>
</f:if>
<f:if condition="{checkboxes.displayThumbs.enabled}">
<div class="form-check">
{checkboxes.displayThumbs.html -> f:format.raw()}
......
......@@ -59,21 +59,7 @@
</f:if>
</td>
<td class="col-control nowrap">
<div class="btn-group">
<f:if condition="{file.isEditable}">
<f:then>
<a href="{fl:uri.editFileContent( file:file.resource, returnUrl:'{f:uri.action( action:\'search\', arguments:\'{ searchWord:\\'{searchWord->f:format.htmlentities()}\\' }\' ) -> f:format.raw()}' )}"
class="btn btn-default filelist-file-edit"
title="{f:translate( key:'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.editcontent' )}"
>
<core:icon identifier="actions-page-open" />
</a>
</f:then>
<f:else>
<span class="btn btn-default disabled"><core:icon identifier="empty-empty" /></span>
</f:else>
</f:if>
<div class="btn-group position-static">
<f:if condition="{file.IsMetadataEditable}">
<f:then>
<a href="{be:uri.editRecord(uid:file.metadataUid, table:'sys_file_metadata', returnUrl:'{f:uri.action( action:\'search\', arguments:\'{ searchWord:\\'{searchWord->f:format.htmlentities()}\\' }\' ) -> f:format.raw()}' )}"
......@@ -101,47 +87,6 @@
</f:else>
</f:if>
<f:if condition="{file.isReplaceable}">
<f:then>
<a href="{fl:uri.replaceFile( file:file.resource, returnUrl:'{f:uri.action( action:\'search\', arguments:\'{ searchWord:\\'{searchWord->f:format.htmlentities()}\\' }\' ) -> f:format.raw()}' )}"
class="btn btn-default filelist-file-replace"
title="{f:translate( key:'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.replace' )}"
>
<core:icon identifier="actions-edit-replace" />
</a>
</f:then>
<f:else>
<span class="btn btn-default disabled"><core:icon identifier="empty-empty" /></span>
</f:else>
</f:if>
<f:if condition="{file.isRenamable}">
<f:then>
<a href="{fl:uri.renameFile( file:file.resource, returnUrl:'{f:uri.action( action:\'search\', arguments:\'{ searchWord:\\'{searchWord->f:format.htmlentities()}\\' }\' ) -> f:format.raw()}' )}"
class="btn btn-default filelist-file-rename"
title="{f:translate( key:'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.rename' )}"
>
<core:icon identifier="actions-edit-rename" />
</a>
</f:then>
<f:else>
<span class="btn btn-default disabled"><core:icon identifier="empty-empty" /></span>
</f:else>
</f:if>
<f:if condition="{file.isReadable}">
<f:then>
<a href="#" class="btn btn-default filelist-file-info"
title="{f:translate( key:'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.info' )}"
data-identifier="{file.identifier}"
>
<core:icon identifier="actions-document-info" />
</a>
</f:then>
<f:else>
<span class="btn btn-default disabled"><core:icon identifier="empty-empty" /></span>
</f:else>
</f:if>
<f:if condition="{file.copyable}">
<f:then>
......@@ -197,6 +142,51 @@
<span class="btn btn-default disabled"><core:icon identifier="empty-empty" /></span>
</f:else>
</f:if>
<div class="btn-group dropdown position-static">
<a href="actions_{file.hashedIdentifier}" class="btn btn-default dropdown-toggle dropdown-toggle-no-chevron" data-bs-toggle="dropdown" data-bs-boundary="window" aria-expanded="false"><core:icon identifier="actions-menu-alternative" /></a>' .
<ul id="actions_{file.hashedIdentifier}" class="dropdown-menu dropdown-list">
<f:if condition="{file.isRenamable}">
<li>
<a href="{fl:uri.renameFile( file:file.resource, returnUrl:'{f:uri.action( action:\'search\', arguments:\'{ searchWord:\\'{searchWord->f:format.htmlentities()}\\' }\' ) -> f:format.raw()}' )}"
class="dropdown-item filelist-file-rename"
title="{f:translate(key:'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.rename')}"
>
<core:icon identifier="actions-edit-rename" /> {f:translate(key:'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.rename')}
</a>
</li>
</f:if>
<f:if condition="{file.isReadable}">
<li>
<a href="#" class="dropdown-item filelist-file-info"
title="{f:translate(key:'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.info')}"
data-identifier="{file.identifier}"
>
<core:icon identifier="actions-document-info" /> {f:translate(key:'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.info')}
</a>
</li>
</f:if>
<f:if condition="{file.isEditable}">
<li>
<a href="{fl:uri.editFileContent( file:file.resource, returnUrl:'{f:uri.action( action:\'search\', arguments:\'{ searchWord:\\'{searchWord->f:format.htmlentities()}\\' }\' ) -> f:format.raw()}' )}"
class="dropdown-item filelist-file-edit"
title="{f:translate(key:'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.editcontent')}"
>
<core:icon identifier="actions-page-open" /> {f:translate( key:'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.editcontent')}
</a>
</li>
</f:if>
<f:if condition="{file.isReplaceable}">
<li>
<a href="{fl:uri.replaceFile( file:file.resource, returnUrl:'{f:uri.action( action:\'search\', arguments:\'{ searchWord:\\'{searchWord->f:format.htmlentities()}\\' }\' ) -> f:format.raw()}' )}"
class="dropdown-item filelist-file-replace"
title="{f:translate(key:'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.replace')}"
>
<core:icon identifier="actions-edit-replace" /> {f:translate( key:'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.replace')}
</a>
</li>
</f:if>
</ul>
</div>
</div>
</td>
<td class="nowrap">{file.extension}</td>
......
......@@ -10,4 +10,4 @@
*
* The TYPO3 project - inspiring people to share!
*/
define(["require","exports","TYPO3/CMS/Core/DocumentService","TYPO3/CMS/Backend/InfoWindow","TYPO3/CMS/Backend/BroadcastMessage","TYPO3/CMS/Backend/BroadcastService","TYPO3/CMS/Backend/Tooltip","TYPO3/CMS/Core/Event/RegularEvent"],(function(e,t,i,o,a,n,d,l){"use strict";class s{static openInfoPopup(e,t){o.showItem(e,t)}static processTriggers(){const e=document.querySelector(".filelist-main");if(null!==e&&(s.emitTreeUpdateRequest(e.dataset.filelistCurrentFolderHash),top.fsMod)){const t=encodeURIComponent(e.dataset.filelistCurrentIdentifier);"object"!=typeof top.fsMod.recentIds?top.fsMod.recentIds={file:t}:top.fsMod.recentIds.file=t}}static registerTreeUpdateEvents(){new l("click",(function(){s.emitTreeUpdateRequest(this.dataset.treeUpdateRequest)})).delegateTo(document.body,"[data-tree-update-request]")}static emitTreeUpdateRequest(e){const t=new a.BroadcastMessage("filelist","treeUpdateRequested",{type:"folder",identifier:e});n.post(t)}static submitClipboardFormWithCommand(e){const t=document.querySelector('form[name="dblistForm"]');t.querySelector('input[name="cmd"]').value=e,t.submit()}constructor(){s.processTriggers(),i.ready().then(()=>{d.initialize(".table-fit a[title]"),s.registerTreeUpdateEvents(),new l("click",(e,t)=>{e.preventDefault(),s.openInfoPopup(t.dataset.filelistShowItemType,t.dataset.filelistShowItemIdentifier)}).delegateTo(document,"[data-filelist-show-item-identifier][data-filelist-show-item-type]"),new l("click",(e,t)=>{e.preventDefault(),s.openInfoPopup("_FILE",t.dataset.identifier)}).delegateTo(document,"a.btn.filelist-file-info"),new l("click",(e,t)=>{e.preventDefault(),s.openInfoPopup("_FILE",t.dataset.identifier)}).delegateTo(document,"a.filelist-file-references"),new l("click",(e,t)=>{e.preventDefault();const i=t.getAttribute("href");let o=i?encodeURIComponent(i):encodeURIComponent(top.list_frame.document.location.pathname+top.list_frame.document.location.search);top.list_frame.location.href=i+"&redirect="+o}).delegateTo(document,"a.btn.filelist-file-copy");const e=document.querySelector('[data-event-name="filelist:clipboard:cmd"]');null!==e&&new l("filelist:clipboard:cmd",(e,t)=>{e.detail.result&&s.submitClipboardFormWithCommand(e.detail.payload)}).bindTo(e),new l("click",(e,t)=>{const i=t.dataset.filelistClipboardCmd;s.submitClipboardFormWithCommand(i)}).delegateTo(document,'[data-filelist-clipboard-cmd]:not([data-filelist-clipboard-cmd=""])')})}}return new s}));
\ No newline at end of file
define(["require","exports","TYPO3/CMS/Core/DocumentService","TYPO3/CMS/Backend/InfoWindow","TYPO3/CMS/Backend/BroadcastMessage","TYPO3/CMS/Backend/BroadcastService","TYPO3/CMS/Backend/Tooltip","TYPO3/CMS/Core/Event/RegularEvent"],(function(e,t,i,o,a,n,d,l){"use strict";class s{static openInfoPopup(e,t){o.showItem(e,t)}static processTriggers(){const e=document.querySelector(".filelist-main");if(null!==e&&(s.emitTreeUpdateRequest(e.dataset.filelistCurrentFolderHash),top.fsMod)){const t=encodeURIComponent(e.dataset.filelistCurrentIdentifier);"object"!=typeof top.fsMod.recentIds?top.fsMod.recentIds={file:t}:top.fsMod.recentIds.file=t}}static registerTreeUpdateEvents(){new l("click",(function(){s.emitTreeUpdateRequest(this.dataset.treeUpdateRequest)})).delegateTo(document.body,"[data-tree-update-request]")}static emitTreeUpdateRequest(e){const t=new a.BroadcastMessage("filelist","treeUpdateRequested",{type:"folder",identifier:e});n.post(t)}static submitClipboardFormWithCommand(e){const t=document.querySelector('form[name="dblistForm"]');t.querySelector('input[name="cmd"]').value=e,t.submit()}constructor(){s.processTriggers(),i.ready().then(()=>{d.initialize(".table-fit a[title]"),s.registerTreeUpdateEvents(),new l("click",(e,t)=>{e.preventDefault(),s.openInfoPopup(t.dataset.filelistShowItemType,t.dataset.filelistShowItemIdentifier)}).delegateTo(document,"[data-filelist-show-item-identifier][data-filelist-show-item-type]"),new l("click",(e,t)=>{e.preventDefault(),s.openInfoPopup("_FILE",t.dataset.identifier)}).delegateTo(document,"a.filelist-file-info"),new l("click",(e,t)=>{e.preventDefault(),s.openInfoPopup("_FILE",t.dataset.identifier)}).delegateTo(document,"a.filelist-file-references"),new l("click",(e,t)=>{e.preventDefault();const i=t.getAttribute("href");let o=i?encodeURIComponent(i):encodeURIComponent(top.list_frame.document.location.pathname+top.list_frame.document.location.search);top.list_frame.location.href=i+"&redirect="+o}).delegateTo(document,"a.filelist-file-copy");const e=document.querySelector('[data-event-name="filelist:clipboard:cmd"]');null!==e&&new l("filelist:clipboard:cmd",(e,t)=>{e.detail.result&&s.submitClipboardFormWithCommand(e.detail.payload)}).bindTo(e),new l("click",(e,t)=>{const i=t.dataset.filelistClipboardCmd;s.submitClipboardFormWithCommand(i)}).delegateTo(document,'[data-filelist-clipboard-cmd]:not([data-filelist-clipboard-cmd=""])')})}}return new s}));
\ No newline at end of file
......@@ -132,7 +132,7 @@ class RecordListController
// Loading module configuration:
$this->modTSconfig = BackendUtility::getPagesTSconfig($this->id)['mod.']['web_list.'] ?? [];
// Clean up settings:
$MOD_SETTINGS = BackendUtility::getModuleData(['bigControlPanel' => '', 'clipBoard' => ''], (array)($parsedBody['SET'] ?? $queryParams['SET'] ?? []), 'web_list');
$MOD_SETTINGS = BackendUtility::getModuleData(['clipBoard' => ''], (array)($parsedBody['SET'] ?? $queryParams['SET'] ?? []), 'web_list');
// main
$lang = $this->getLanguageService();
// Loading current page record and checking access:
......@@ -150,12 +150,6 @@ class RecordListController
}
$this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/PageActions', $pageActionsCallback);
// Apply predefined values for hidden checkboxes
// Set predefined value for DisplayBigControlPanel:
if ($this->modTSconfig['enableDisplayBigControlPanel'] === 'activated') {
$MOD_SETTINGS['bigControlPanel'] = true;
} elseif ($this->modTSconfig['enableDisplayBigControlPanel'] === 'deactivated') {
$MOD_SETTINGS['bigControlPanel'] = false;
}
// Set predefined value for Clipboard:
if (isset($this->modTSconfig['enableClipBoard'])) {
if ($this->modTSconfig['enableClipBoard'] === 'activated') {
......@@ -331,16 +325,6 @@ class RecordListController
<div class="typo3-listOptions">
<form action="" method="post">';
// Add "display bigControlPanel" checkbox:
if ($this->modTSconfig['enableDisplayBigControlPanel'] === 'selectable') {
$body .= '<div class="form-check">' .
BackendUtility::getFuncCheck($this->id, 'SET[bigControlPanel]', $MOD_SETTINGS['bigControlPanel'] ?? '', '', $table ? '&table=' . $table : '', 'id="checkLargeControl"') .
'<label for="checkLargeControl" class="form-check-label">' .
BackendUtility::wrapInHelp('xMOD_csh_corebe', 'list_options', htmlspecialchars($lang->getLL('largeControl'))) .
'</label>' .
'</div>';
}
// Add "clipboard" checkbox:
if ($this->modTSconfig['enableClipBoard'] === 'selectable') {
$body .= '<div class="form-check">' .
......
......@@ -753,16 +753,16 @@ class DatabaseRecordList
$collapseClass = $tableCollapsed && !$this->table ? 'collapse' : 'collapse show';
$dataState = $tableCollapsed && !$this->table ? 'collapsed' : 'expanded';
return '
<div class="panel panel-space panel-default recordlist" id="t3-table-' . htmlspecialchars($tableIdentifier) . '">
<div class="recordlist mb-4 mt-4 border" id="t3-table-' . htmlspecialchars($tableIdentifier) . '">
<form action="' . htmlspecialchars($this->listURL()) . '#t3-table-' . htmlspecialchars($tableIdentifier) . '" method="post" name="list-table-form-' . htmlspecialchars($tableIdentifier) . '">
<input type="hidden" name="cmd_table" />
<input type="hidden" name="cmd" />
<div class="panel-heading">
<div class="recordlist-heading">
' . $tableHeader . '
</div>
<div class="' . $collapseClass . '" data-state="' . $dataState . '" id="recordlist-' . htmlspecialchars($tableIdentifier) . '">
<div class="table-fit">
<table data-table="' . htmlspecialchars($tableIdentifier) . '" class="table table-striped table-hover">
<div class="table-fit mb-0">
<table data-table="' . htmlspecialchars($tableIdentifier) . '" class="table table-striped table-hover mb-0">
' . $columnsOutput . $rowOutput . '
</table>
</div>
......@@ -1517,35 +1517,6 @@ class DatabaseRecordList
}
}
// "Up/Down" links
if ($permsEdit && ($GLOBALS['TCA'][$table]['ctrl']['sortby'] ?? false) && !$this->sortField && !$this->searchLevels) {
if (!$isL10nOverlay && !$isDeletePlaceHolder && isset($this->currentTable['prev'][$row['uid']])) {
// Up
$params = [];
$params['redirect'] = $this->listURL();
$params['cmd'][$table][$row['uid']]['move'] = $this->currentTable['prev'][$row['uid']];
$url = (string)$this->uriBuilder->buildUriFromRoute('tce_db', $params);
$moveUpAction = '<a class="btn btn-default" href="' . htmlspecialchars($url) . '" title="' . htmlspecialchars($this->getLanguageService()->getLL('moveUp')) . '">'
. $this->iconFactory->getIcon('actions-move-up', Icon::SIZE_SMALL)->render() . '</a>';
} else {
$moveUpAction = $this->spaceIcon;
}
$this->addActionToCellGroup($cells, $moveUpAction, 'moveUp');
if (!$isL10nOverlay && !$isDeletePlaceHolder && !empty($this->currentTable['next'][$row['uid']])) {
// Down
$params = [];
$params['redirect'] = $this->listURL();
$params['cmd'][$table][$row['uid']]['move'] = $this->currentTable['next'][$row['uid']];
$url = (string)$this->uriBuilder->buildUriFromRoute('tce_db', $params);
$moveDownAction = '<a class="btn btn-default" href="' . htmlspecialchars($url) . '" title="' . htmlspecialchars($this->getLanguageService()->getLL('moveDown')) . '">'
. $this->iconFactory->getIcon('actions-move-down', Icon::SIZE_SMALL)->render() . '</a>';
} else {
$moveDownAction = $this->spaceIcon;
}
$this->addActionToCellGroup($cells, $moveDownAction, 'moveDown');
}
// "Hide/Unhide" links:
$hiddenField = $GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['disabled'] ?? null;
if ($hiddenField !== null
......@@ -1582,6 +1553,35 @@ class DatabaseRecordList
$this->addActionToCellGroup($cells, $hideAction, 'hide');
}
// "Up/Down" links
if ($permsEdit && ($GLOBALS['TCA'][$table]['ctrl']['sortby'] ?? false) && !$this->sortField && !$this->searchLevels) {
if (!$isL10nOverlay && !$isDeletePlaceHolder && isset($this->currentTable['prev'][$row['uid']])) {
// Up
$params = [];
$params['redirect'] = $this->listURL();
$params['cmd'][$table][$row['uid']]['move'] = $this->currentTable['prev'][$row['uid']];
$url = (string)$this->uriBuilder->buildUriFromRoute('tce_db', $params);
$moveUpAction = '<a class="btn btn-default" href="' . htmlspecialchars($url) . '" title="' . htmlspecialchars($this->getLanguageService()->getLL('moveUp')) . '">'
. $this->iconFactory->getIcon('actions-move-up', Icon::SIZE_SMALL)->render() . '</a>';
} else {
$moveUpAction = $this->spaceIcon;
}
$this->addActionToCellGroup($cells, $moveUpAction, 'moveUp');
if (!$isL10nOverlay && !$isDeletePlaceHolder && !empty($this->currentTable['next'][$row['uid']])) {
// Down
$params = [];
$params['redirect'