Skip to content

Commit 0cad91b

Browse files
authored
Merge pull request #6247 from WoltLab/6.2-NoticeListPage-to-grid-view
Migrate `NoticeListPage` to grid view
2 parents 260ad70 + 5a88910 commit 0cad91b

File tree

14 files changed

+474
-124
lines changed

14 files changed

+474
-124
lines changed
Lines changed: 20 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,80 +1,39 @@
11
{include file='header' pageTitle='wcf.acp.notice.list'}
22

3-
<script data-relocate="true">
4-
require(['WoltLabSuite/Core/Ui/Sortable/List'], function (UiSortableList) {
5-
new UiSortableList({
6-
containerId: 'noticeList',
7-
className: 'wcf\\data\\notice\\NoticeAction',
8-
offset: {@$startIndex}
9-
});
10-
});
11-
</script>
12-
133
<header class="contentHeader">
144
<div class="contentHeaderTitle">
15-
<h1 class="contentTitle">{lang}wcf.acp.notice.list{/lang}{if $items} <span class="badge badgeInverse">{#$items}</span>{/if}</h1>
5+
<h1 class="contentTitle">{lang}wcf.acp.notice.list{/lang} <span class="badge badgeInverse">{#$gridView->countRows()}</span></h1>
166
</div>
177

188
<nav class="contentHeaderNavigation">
199
<ul>
10+
{if $gridView->countRows() > 1}
11+
<li>
12+
<button type="button" class="button jsChangeShowOrder">{icon name='up-down'} <span>{lang}wcf.global.changeShowOrder{/lang}</span></button>
13+
</li>
14+
{/if}
2015
<li><a href="{link controller='NoticeAdd'}{/link}" class="button">{icon name='plus'} <span>{lang}wcf.acp.menu.link.notice.add{/lang}</span></a></li>
2116

2217
{event name='contentHeaderNavigation'}
2318
</ul>
2419
</nav>
2520
</header>
2621

27-
{hascontent}
28-
<div class="paginationTop">
29-
{content}{pages print=true assign=pagesLinks controller="NoticeList" link="pageNo=%d&sortField=$sortField&sortOrder=$sortOrder"}{/content}
30-
</div>
31-
{/hascontent}
22+
<div class="section">
23+
{unsafe:$gridView->render()}
24+
</div>
3225

33-
{if $objects|count}
34-
<div class="section sortableListContainer" id="noticeList">
35-
<ol class="sortableList jsReloadPageWhenEmpty jsObjectActionContainer" data-object-action-class-name="wcf\data\notice\NoticeAction" data-object-id="0" start="{@($pageNo - 1) * $itemsPerPage + 1}">
36-
{foreach from=$objects item='notice'}
37-
<li class="sortableNode sortableNoNesting jsNotice jsObjectActionObject" data-object-id="{@$notice->getObjectID()}">
38-
<span class="sortableNodeLabel">
39-
<a href="{link controller='NoticeEdit' object=$notice}{/link}">{$notice->noticeName}</a>
40-
41-
<span class="statusDisplay sortableButtonContainer">
42-
<span class="sortableNodeHandle">
43-
{icon name='arrows-up-down-left-right'}
44-
</span>
45-
{objectAction action="toggle" isDisabled=$notice->isDisabled}
46-
<a href="{link controller='NoticeEdit' object=$notice}{/link}" title="{lang}wcf.global.button.edit{/lang}" class="jsTooltip">{icon name='pencil'}</a>
47-
{objectAction action="delete" objectTitle=$notice->noticeName}
48-
49-
{event name='itemButtons'}
50-
</span>
51-
</span>
52-
</li>
53-
{/foreach}
54-
</ol>
55-
</div>
56-
57-
<div class="formSubmit">
58-
<button type="button" class="button buttonPrimary" data-type="submit">{lang}wcf.global.button.saveSorting{/lang}</button>
59-
</div>
60-
61-
<footer class="contentFooter">
62-
{hascontent}
63-
<div class="paginationBottom">
64-
{content}{@$pagesLinks}{/content}
65-
</div>
66-
{/hascontent}
67-
68-
<nav class="contentFooterNavigation">
69-
<ul>
70-
<li><a href="{link controller='NoticeAdd'}{/link}" class="button">{icon name='plus'} <span>{lang}wcf.acp.menu.link.notice.add{/lang}</span></a></li>
71-
72-
{event name='contentFooterNavigation'}
73-
</ul>
74-
</nav>
75-
</footer>
76-
{else}
77-
<woltlab-core-notice type="info">{lang}wcf.global.noItems{/lang}</woltlab-core-notice>
26+
{if $gridView->countRows() > 1}
27+
<script data-relocate="true">
28+
require(["WoltLabSuite/Core/Component/ChangeShowOrder"], ({ setup }) => {
29+
{jsphrase name='wcf.global.changeShowOrder'}
30+
31+
setup(
32+
document.querySelector('.jsChangeShowOrder'),
33+
'core/notices/show-order',
34+
);
35+
});
36+
</script>
7837
{/if}
7938

8039
{include file='footer'}

wcfsetup/install/files/lib/acp/page/NoticeListPage.class.php

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22

33
namespace wcf\acp\page;
44

5-
use wcf\data\notice\NoticeList;
6-
use wcf\page\SortablePage;
5+
use wcf\page\AbstractGridViewPage;
6+
use wcf\system\gridView\AbstractGridView;
7+
use wcf\system\gridView\admin\NoticeGridView;
78

89
/**
910
* Lists the available notices.
@@ -12,32 +13,23 @@
1213
* @copyright 2001-2019 WoltLab GmbH
1314
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
1415
*
15-
* @extends SortablePage<NoticeList>
16+
* @extends AbstractGridViewPage<NoticeGridView>
1617
*/
17-
class NoticeListPage extends SortablePage
18+
class NoticeListPage extends AbstractGridViewPage
1819
{
1920
/**
2021
* @inheritDoc
2122
*/
2223
public $activeMenuItem = 'wcf.acp.menu.link.notice.list';
2324

24-
/**
25-
* @inheritDoc
26-
*/
27-
public $defaultSortField = 'showOrder';
28-
2925
/**
3026
* @inheritDoc
3127
*/
3228
public $neededPermissions = ['admin.notice.canManageNotice'];
3329

34-
/**
35-
* @inheritDoc
36-
*/
37-
public $objectListClassName = NoticeList::class;
38-
39-
/**
40-
* @inheritDoc
41-
*/
42-
public $validSortFields = ['noticeID', 'noticeName', 'showOrder'];
30+
#[\Override]
31+
protected function createGridView(): AbstractGridView
32+
{
33+
return new NoticeGridView();
34+
}
4335
}

wcfsetup/install/files/lib/bootstrap/com.woltlab.wcf.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,11 @@ static function (\wcf\event\endpoint\ControllerCollecting $event) {
222222
$event->register(new \wcf\system\endpoint\controller\core\ads\DeleteAd());
223223
$event->register(new \wcf\system\endpoint\controller\core\ads\GetShowOrder());
224224
$event->register(new \wcf\system\endpoint\controller\core\ads\ChangeShowOrder());
225+
$event->register(new \wcf\system\endpoint\controller\core\notices\EnableNotice());
226+
$event->register(new \wcf\system\endpoint\controller\core\notices\DisableNotice());
227+
$event->register(new \wcf\system\endpoint\controller\core\notices\DeleteNotice());
228+
$event->register(new \wcf\system\endpoint\controller\core\notices\GetShowOrder());
229+
$event->register(new \wcf\system\endpoint\controller\core\notices\ChangeShowOrder());
225230
}
226231
);
227232

wcfsetup/install/files/lib/data/notice/NoticeAction.class.php

Lines changed: 1 addition & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,9 @@
33
namespace wcf\data\notice;
44

55
use wcf\data\AbstractDatabaseObjectAction;
6-
use wcf\data\ISortableAction;
76
use wcf\data\IToggleAction;
87
use wcf\data\TDatabaseObjectToggle;
98
use wcf\system\condition\ConditionHandler;
10-
use wcf\system\exception\UserInputException;
119
use wcf\system\user\storage\UserStorageHandler;
1210
use wcf\system\WCF;
1311

@@ -20,7 +18,7 @@
2018
*
2119
* @extends AbstractDatabaseObjectAction<Notice, NoticeEditor>
2220
*/
23-
class NoticeAction extends AbstractDatabaseObjectAction implements ISortableAction, IToggleAction
21+
class NoticeAction extends AbstractDatabaseObjectAction implements IToggleAction
2422
{
2523
use TDatabaseObjectToggle;
2624

@@ -121,27 +119,6 @@ public function validateDismiss()
121119
$this->getSingleObject();
122120
}
123121

124-
/**
125-
* @inheritDoc
126-
*/
127-
public function validateUpdatePosition()
128-
{
129-
WCF::getSession()->checkPermissions($this->permissionsUpdate);
130-
131-
if (!isset($this->parameters['data']['structure']) || !\is_array($this->parameters['data']['structure'])) {
132-
throw new UserInputException('structure');
133-
}
134-
135-
$noticeList = new NoticeList();
136-
$noticeList->setObjectIDs($this->parameters['data']['structure'][0]);
137-
$noticeList->readObjects();
138-
if (\count($noticeList) !== \count($this->parameters['data']['structure'][0])) {
139-
throw new UserInputException('structure');
140-
}
141-
142-
$this->readInteger('offset', true, 'data');
143-
}
144-
145122
/**
146123
* @inheritDoc
147124
*/
@@ -157,25 +134,4 @@ public function update()
157134
\reset($this->objects)->setShowOrder($this->parameters['data']['showOrder']);
158135
}
159136
}
160-
161-
/**
162-
* @inheritDoc
163-
*/
164-
public function updatePosition()
165-
{
166-
$sql = "UPDATE wcf1_notice
167-
SET showOrder = ?
168-
WHERE noticeID = ?";
169-
$statement = WCF::getDB()->prepare($sql);
170-
171-
$showOrder = $this->parameters['data']['offset'];
172-
WCF::getDB()->beginTransaction();
173-
foreach ($this->parameters['data']['structure'][0] as $noticeID) {
174-
$statement->execute([
175-
$showOrder++,
176-
$noticeID,
177-
]);
178-
}
179-
WCF::getDB()->commitTransaction();
180-
}
181137
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
namespace wcf\event\interaction\admin;
4+
5+
use wcf\event\IPsr14Event;
6+
use wcf\system\interaction\admin\NoticeInteractions;
7+
8+
/**
9+
* Indicates that the provider for notice interactions is collecting interactions.
10+
*
11+
* @author Olaf Braun
12+
* @copyright 2001-2025 WoltLab GmbH
13+
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
14+
* @since 6.2
15+
*/
16+
final class NoticeInteractionCollecting implements IPsr14Event
17+
{
18+
public function __construct(public readonly NoticeInteractions $param)
19+
{
20+
}
21+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
namespace wcf\event\interaction\bulk\admin;
4+
5+
use wcf\event\IPsr14Event;
6+
use wcf\system\interaction\bulk\admin\NoticeBulkInteractions;
7+
8+
/**
9+
* Indicates that the provider for notice bulk interactions is collecting interactions.
10+
*
11+
* @author Olaf Braun
12+
* @copyright 2001-2025 WoltLab GmbH
13+
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
14+
* @since 6.2
15+
*/
16+
final class NoticeBulkInteractionCollecting implements IPsr14Event
17+
{
18+
public function __construct(public readonly NoticeBulkInteractions $param)
19+
{
20+
}
21+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?php
2+
3+
namespace wcf\system\endpoint\controller\core\notices;
4+
5+
use Laminas\Diactoros\Response\JsonResponse;
6+
use Psr\Http\Message\ResponseInterface;
7+
use Psr\Http\Message\ServerRequestInterface;
8+
use wcf\data\notice\Notice;
9+
use wcf\data\notice\NoticeCache;
10+
use wcf\data\notice\NoticeList;
11+
use wcf\system\cache\builder\NoticeCacheBuilder;
12+
use wcf\system\endpoint\IController;
13+
use wcf\system\endpoint\PostRequest;
14+
use wcf\system\showOrder\ShowOrderHandler;
15+
use wcf\system\showOrder\ShowOrderItem;
16+
use wcf\system\WCF;
17+
18+
/**
19+
* API endpoint for changing the show order of notices.
20+
*
21+
* @author Olaf Braun
22+
* @copyright 2001-2025 WoltLab GmbH
23+
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
24+
* @since 6.2
25+
*/
26+
#[PostRequest('/core/notices/show-order')]
27+
final class ChangeShowOrder implements IController
28+
{
29+
public function __invoke(ServerRequestInterface $request, array $variables): ResponseInterface
30+
{
31+
WCF::getSession()->checkPermissions(['admin.notice.canManageNotice']);
32+
33+
$noticeList = new NoticeList();
34+
$noticeList->sqlOrderBy = 'showOrder ASC';
35+
$noticeList->readObjects();
36+
37+
$items = \array_map(
38+
static fn(Notice $notice) => new ShowOrderItem($notice->noticeID, $notice->getTitle()),
39+
$noticeList->getObjects()
40+
);
41+
42+
$sortedItems = (new ShowOrderHandler($items))->getSortedItemsFromRequest($request);
43+
$this->saveShowOrder($sortedItems);
44+
45+
return new JsonResponse([]);
46+
}
47+
48+
/**
49+
* @param list<ShowOrderItem> $items
50+
*/
51+
private function saveShowOrder(array $items): void
52+
{
53+
WCF::getDB()->beginTransaction();
54+
$sql = "UPDATE wcf1_notice
55+
SET showOrder = ?
56+
WHERE noticeID = ?";
57+
$statement = WCF::getDB()->prepare($sql);
58+
for ($i = 0, $length = \count($items); $i < $length; $i++) {
59+
$statement->execute([
60+
$i + 1,
61+
$items[$i]->id,
62+
]);
63+
}
64+
WCF::getDB()->commitTransaction();
65+
66+
NoticeCacheBuilder::getInstance()->reset();
67+
}
68+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
namespace wcf\system\endpoint\controller\core\notices;
4+
5+
use Laminas\Diactoros\Response\JsonResponse;
6+
use Psr\Http\Message\ResponseInterface;
7+
use Psr\Http\Message\ServerRequestInterface;
8+
use wcf\data\notice\Notice;
9+
use wcf\data\notice\NoticeAction;
10+
use wcf\http\Helper;
11+
use wcf\system\endpoint\DeleteRequest;
12+
use wcf\system\endpoint\IController;
13+
use wcf\system\WCF;
14+
15+
/**
16+
* API endpoint for deleting notices.
17+
*
18+
* @author Olaf Braun
19+
* @copyright 2001-2025 WoltLab GmbH
20+
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
21+
* @since 6.2
22+
*/
23+
#[DeleteRequest("/core/notices/{id:\d+}")]
24+
final class DeleteNotice implements IController
25+
{
26+
#[\Override]
27+
public function __invoke(ServerRequestInterface $request, array $variables): ResponseInterface
28+
{
29+
WCF::getSession()->checkPermissions(['admin.notice.canManageNotice']);
30+
31+
$notice = Helper::fetchObjectFromRequestParameter($variables['id'], Notice::class);
32+
33+
(new NoticeAction([$notice], 'delete'))->executeAction();
34+
35+
return new JsonResponse([]);
36+
}
37+
}

0 commit comments

Comments
 (0)