Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions com.woltlab.wcf/templates/boxListView.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div class="{$containerCssClassName}">
{unsafe:$listView->render()}
</div>
2 changes: 1 addition & 1 deletion com.woltlab.wcf/templates/shared_listView.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
</div>
</div>

<div class="listView__footer" id="{$view->getID()}_footer">
<div class="listView__footer" id="{$view->getID()}_footer"{if $view->countPages() < 2} hidden{/if}>
{if $view->hasBulkInteractions()}
<div id="{$view->getID()}_selectionBar" class="listView__selectionBar dropdown" hidden>
<button type="button" id="{$view->getID()}_bulkInteractionButton" class="button small listView__bulkInteractionButton dropdownToggle"></button>
Expand Down
4 changes: 4 additions & 0 deletions ts/WoltLabSuite/Core/Component/ListView/Selection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ export class Selection extends EventTarget {
this.#restoreSelection();
}

selectionBarVisible(): boolean {
return this.#selectionBar !== null && this.getSelectedIds().length > 0;
}

refresh(): void {
this.#restoreSelection();
}
Expand Down
2 changes: 1 addition & 1 deletion ts/WoltLabSuite/Core/Component/ListView/State.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ export class State extends EventTarget {
}

#updateListViewFooter(): void {
this.#listViewFooter.hidden = this.#pagination.count < 2 && this.#selection.getSelectedIds().length === 0;
this.#listViewFooter.hidden = this.#pagination.count < 2 && !this.#selection.selectionBarVisible();
}

setBulkInteractionContextMenuOptions(options: string): void {
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
<?php

namespace wcf\system\box;

use wcf\system\condition\IObjectListCondition;
use wcf\system\event\EventHandler;
use wcf\system\listView\AbstractListView;
use wcf\system\WCF;

/**
* Default implementation of a box controller based on a list view.
*
* @author Marcel Werk
* @copyright 2001-2025 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
* @since 6.2
*
* @template TListView of AbstractListView
*/
abstract class AbstractListViewBoxController extends AbstractDatabaseObjectListBoxController
{
/**
* @var TListView
*/
protected AbstractListView $listView;

/**
* @return TListView
*/
protected function getListView(): AbstractListView
{
if (!isset($this->listView)) {
$this->listView = $this->createListView();
$this->listView->setAllowFiltering(false);
$this->listView->setAllowSorting(false);
$this->listView->setAllowBulkInteractions(false);
}

return $this->listView;
}

/**
* @return TListView
*/
protected abstract function createListView(): AbstractListView;

#[\Override]
public function hasContent()
{
EventHandler::getInstance()->fireAction($this, 'hasContent');

if ($this->objectList === null) {
$this->loadContent();
}

return $this->getListView()->countItems() > 0;
}

#[\Override]
protected function loadContent()
{
EventHandler::getInstance()->fireAction($this, 'beforeLoadContent');

if ($this->limit) {
$this->getListView()->setFixedNumberOfItems($this->limit);
}

if ($this->sortOrder && $this->sortField) {
$this->getListView()->setSortField($this->sortField);
$this->getListView()->getSortOrder($this->sortOrder);
}

$this->objectList = $this->getObjectList();

if ($this->conditionDefinition) {
foreach ($this->box->getControllerConditions() as $condition) {
$processor = $condition->getObjectType()->getProcessor();
if ($processor instanceof IObjectListCondition) {
$processor->addObjectListCondition($this->objectList, $condition->conditionData);
}
}
}

$this->content = $this->getTemplate();

EventHandler::getInstance()->fireAction($this, 'afterLoadContent');
}

#[\Override]
protected function getObjectList()
{
return $this->getListView()->getObjectList();
}

#[\Override]
protected function getTemplate()
{
return WCF::getTPL()->render('wcf', 'boxListView', [
'listView' => $this->listView,
'containerCssClassName' => $this->getContainerCssClassName(),
]);
}

public function getContainerCssClassName(): string
{
return '';
}

#[\Override]
protected function readObjects()
{
// Does nothing.
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace wcf\system\box;

use wcf\data\article\AccessibleArticleList;
use wcf\system\listView\user\ArticleListView;
use wcf\system\WCF;

/**
Expand All @@ -13,9 +13,9 @@
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
* @since 3.0
*
* @extends AbstractDatabaseObjectListBoxController<AccessibleArticleList>
* @extends AbstractListViewBoxController<ArticleListView>
*/
class ArticleListBoxController extends AbstractDatabaseObjectListBoxController
class ArticleListBoxController extends AbstractListViewBoxController
{
/**
* @inheritDoc
Expand Down Expand Up @@ -51,12 +51,8 @@ class ArticleListBoxController extends AbstractDatabaseObjectListBoxController
public $validSortFields = [
'time',
'views',
'random',
];

/**
* @inheritDoc
*/
public function __construct()
{
if (!empty($this->validSortFields) && MODULE_LIKE) {
Expand All @@ -66,35 +62,42 @@ public function __construct()
parent::__construct();
}

/**
* @inheritDoc
*/
#[\Override]
protected function getObjectList()
{
$objectList = new AccessibleArticleList();
$objectList = $this->getListView()->getObjectList();

switch ($this->sortField) {
case 'views':
$objectList->getConditionBuilder()->add('article.views > ?', [0]);
break;
}

if ($this->sortField === 'random') {
$this->sortField = 'RAND()';
}

return $objectList;
}

/**
* @inheritDoc
*/
#[\Override]
protected function createListView(): ArticleListView
{
return new ArticleListView();
}

#[\Override]
public function getContainerCssClassName(): string
{
return 'entryCardList__container';
}

#[\Override]
protected function getTemplate()
{
return WCF::getTPL()->render('wcf', 'boxArticleList', [
'boxArticleList' => $this->objectList,
'boxSortField' => $this->sortField,
'boxPosition' => $this->box->position,
]);
return match ($this->box->position) {
'top', 'bottom', 'contentTop', 'contentBottom' => parent::getTemplate(),
default => WCF::getTPL()->render('wcf', 'boxArticleList', [
'boxArticleList' => $this->getListView()->getItems(),
'boxSortField' => $this->sortField,
'boxPosition' => $this->box->position,
])
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ abstract class AbstractListView
private bool $allowFiltering = true;
private bool $allowSorting = true;
private bool $allowInteractions = true;
private bool $allowBulkInteractions = true;
private int $fixedNumberOfItems = 0;

/**
Expand Down Expand Up @@ -479,7 +480,7 @@ public function getBulkInteractionProvider(): ?IBulkInteractionProvider
*/
public function hasBulkInteractions(): bool
{
return $this->allowInteractions
return $this->allowBulkInteractions
&& $this->getBulkInteractionProvider() !== null
&& $this->getBulkInteractionProvider()->getInteractions() !== [];
}
Expand All @@ -498,6 +499,11 @@ public function setAllowInteractions(bool $allowInteractions): void
$this->allowInteractions = $allowInteractions;
}

public function setAllowBulkInteractions(bool $allowBulkInteractions): void
{
$this->allowBulkInteractions = $allowBulkInteractions;
}

/**
* Returns true, if this list view has interactions.
*/
Expand Down