Skip to content

Commit 4e885b7

Browse files
committed
Migrate ReactionTypeListPage to grid view
1 parent 0cad91b commit 4e885b7

File tree

16 files changed

+628
-133
lines changed

16 files changed

+628
-133
lines changed
Lines changed: 20 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,91 +1,39 @@
11
{include file='header' pageTitle='wcf.acp.menu.link.reactionType.list'}
22

3-
{if $objects|count}
4-
<script data-relocate="true">
5-
require(['WoltLabSuite/Core/Ui/Sortable/List'], function (UiSortableList) {
6-
new UiSortableList({
7-
containerId: 'reactionTypeList',
8-
className: 'wcf\\data\\reaction\\type\\ReactionTypeAction',
9-
offset: {@$startIndex}
10-
});
11-
});
12-
</script>
13-
{/if}
14-
153
<header class="contentHeader">
164
<div class="contentHeaderTitle">
17-
<h1 class="contentTitle">{lang}wcf.acp.menu.link.reactionType.list{/lang}{if $items} <span class="badge badgeInverse">{#$items}</span>{/if}</h1>
5+
<h1 class="contentTitle">{lang}wcf.acp.menu.link.reactionType.list{/lang} <span class="badge badgeInverse">{#$gridView->countRows()}</span></h1>
186
</div>
197

208
<nav class="contentHeaderNavigation">
219
<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}
2215
<li><a href="{link controller='ReactionTypeAdd'}{/link}" class="button">{icon name='plus'} <span>{lang}wcf.acp.menu.link.reactionType.add{/lang}</span></a></li>
2316

2417
{event name='contentHeaderNavigation'}
2518
</ul>
2619
</nav>
2720
</header>
2821

29-
{hascontent}
30-
<div class="paginationTop">
31-
{content}{pages print=true assign=pagesLinks controller="ReactionTypeList" link="pageNo=%d"}{/content}
32-
</div>
33-
{/hascontent}
22+
<div class="section">
23+
{unsafe:$gridView->render()}
24+
</div>
3425

35-
{if $objects|count}
36-
<div id="reactionTypeList" class="sortableListContainer section">
37-
<ol class="sortableList jsReloadPageWhenEmpty jsObjectActionContainer" data-object-action-class-name="wcf\data\reaction\type\ReactionTypeAction" data-object-id="0" start="{@($pageNo - 1) * $itemsPerPage + 1}">
38-
{foreach from=$objects item=reactionType}
39-
<li class="sortableNode sortableNoNesting reactionTypeRow jsObjectActionObject" data-object-id="{@$reactionType->getObjectID()}">
40-
<span class="sortableNodeLabel">
41-
<a href="{link controller='ReactionTypeEdit' id=$reactionType->reactionTypeID}{/link}">{@$reactionType->renderIcon()} {$reactionType->getTitle()}</a>
42-
43-
<span class="statusDisplay sortableButtonContainer">
44-
<span class="sortableNodeHandle">
45-
{icon name='arrows-up-down-left-right'}
46-
</span>
47-
{assign var='reactionTypeIsDisabled' value=true}
48-
{if $reactionType->isAssignable}
49-
{assign var='reactionTypeIsDisabled' value=false}
50-
{/if}
51-
{objectAction action="toggle" isDisabled=$reactionTypeIsDisabled disableTitle='wcf.acp.reactionType.isAssignable' enableTitle='wcf.acp.reactionType.isNotAssignable'}
52-
<a href="{link controller='ReactionTypeEdit' id=$reactionType->reactionTypeID}{/link}" class="jsTooltip" title="{lang}wcf.global.button.edit{/lang}">
53-
{icon name='pencil'}
54-
</a>
55-
{objectAction action="delete" objectTitle=$reactionType->getTitle()}
56-
57-
{event name='itemButtons'}
58-
</span>
59-
</span>
60-
<ol class="sortableList" data-object-id="{@$reactionType->reactionTypeID}"></ol>
61-
</li>
62-
{/foreach}
63-
</ol>
64-
</div>
65-
66-
<div class="formSubmit">
67-
<button type="button" class="button buttonPrimary" data-type="submit">{lang}wcf.global.button.saveSorting{/lang}</button>
68-
</div>
69-
70-
<footer class="contentFooter">
71-
{hascontent}
72-
<div class="paginationBottom">
73-
{content}{@$pagesLinks}{/content}
74-
</div>
75-
{/hascontent}
76-
77-
{hascontent}
78-
<nav class="contentFooterNavigation">
79-
<ul>
80-
{content}
81-
{event name='contentFooterNavigation'}
82-
{/content}
83-
</ul>
84-
</nav>
85-
{/hascontent}
86-
</footer>
87-
{else}
88-
<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/reactions/types/show-order',
34+
);
35+
});
36+
</script>
8937
{/if}
9038

9139
{include file='footer'}

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

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,20 @@
22

33
namespace wcf\acp\page;
44

5-
use wcf\data\reaction\type\ReactionTypeList;
6-
use wcf\page\MultipleLinkPage;
5+
use wcf\page\AbstractGridViewPage;
6+
use wcf\system\gridView\AbstractGridView;
7+
use wcf\system\gridView\admin\ReactionTypeGridView;
78

89
/**
910
* Shows the list of reaction types.
1011
*
11-
* @author Joshua Ruesweg
12-
* @copyright 2001-2019 WoltLab GmbH
12+
* @author Olaf Braun, Joshua Ruesweg
13+
* @copyright 2001-2025 WoltLab GmbH
1314
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
1415
*
15-
* @extends MultipleLinkPage<ReactionTypeList>
16+
* @extends AbstractGridViewPage<ReactionTypeGridView>
1617
*/
17-
class ReactionTypeListPage extends MultipleLinkPage
18+
class ReactionTypeListPage extends AbstractGridViewPage
1819
{
1920
/**
2021
* @inheritDoc
@@ -31,13 +32,9 @@ class ReactionTypeListPage extends MultipleLinkPage
3132
*/
3233
public $neededPermissions = ['admin.content.reaction.canManageReactionType'];
3334

34-
/**
35-
* @inheritDoc
36-
*/
37-
public $sqlOrderBy = 'showOrder ASC, reactionTypeID ASC';
38-
39-
/**
40-
* @inheritDoc
41-
*/
42-
public $objectListClassName = ReactionTypeList::class;
35+
#[\Override]
36+
protected function createGridView(): AbstractGridView
37+
{
38+
return new ReactionTypeGridView();
39+
}
4340
}

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,11 @@ static function (\wcf\event\endpoint\ControllerCollecting $event) {
227227
$event->register(new \wcf\system\endpoint\controller\core\notices\DeleteNotice());
228228
$event->register(new \wcf\system\endpoint\controller\core\notices\GetShowOrder());
229229
$event->register(new \wcf\system\endpoint\controller\core\notices\ChangeShowOrder());
230+
$event->register(new \wcf\system\endpoint\controller\core\reactions\types\Assignable());
231+
$event->register(new \wcf\system\endpoint\controller\core\reactions\types\NotAssignable());
232+
$event->register(new \wcf\system\endpoint\controller\core\reactions\types\DeleteType());
233+
$event->register(new \wcf\system\endpoint\controller\core\reactions\types\GetShowOrder());
234+
$event->register(new \wcf\system\endpoint\controller\core\reactions\types\ChangeShowOrder());
230235
}
231236
);
232237

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
namespace wcf\data\reaction\type;
4+
5+
use wcf\data\I18nDatabaseObjectList;
6+
7+
/**
8+
* I18n implementation of a reaction type list.
9+
*
10+
* @author Olaf Braun
11+
* @copyright 2001-2025 WoltLab GmbH
12+
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
13+
* @since 6.2
14+
*
15+
* @extends I18nDatabaseObjectList<ReactionType>
16+
*/
17+
class I18nReactionTypeList extends I18nDatabaseObjectList
18+
{
19+
/**
20+
* @inheritDoc
21+
*/
22+
public $i18nFields = ["title" => "titleI18n"];
23+
24+
/**
25+
* @inheritDoc
26+
*/
27+
public $className = ReactionType::class;
28+
}

wcfsetup/install/files/lib/data/reaction/type/ReactionTypeAction.class.php

Lines changed: 2 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,8 @@
33
namespace wcf\data\reaction\type;
44

55
use wcf\data\AbstractDatabaseObjectAction;
6-
use wcf\data\ISortableAction;
76
use wcf\data\IToggleAction;
87
use wcf\data\TDatabaseObjectToggle;
9-
use wcf\system\exception\PermissionDeniedException;
10-
use wcf\system\exception\UserInputException;
118
use wcf\system\file\upload\UploadFile;
129
use wcf\system\language\I18nHandler;
1310
use wcf\system\WCF;
@@ -22,7 +19,7 @@
2219
*
2320
* @extends AbstractDatabaseObjectAction<ReactionType, ReactionTypeEditor>
2421
*/
25-
class ReactionTypeAction extends AbstractDatabaseObjectAction implements ISortableAction, IToggleAction
22+
class ReactionTypeAction extends AbstractDatabaseObjectAction implements IToggleAction
2623
{
2724
use TDatabaseObjectToggle;
2825

@@ -39,7 +36,7 @@ class ReactionTypeAction extends AbstractDatabaseObjectAction implements ISortab
3936
/**
4037
* @inheritDoc
4138
*/
42-
protected $requireACP = ['delete', 'update', 'updatePosition'];
39+
protected $requireACP = ['delete', 'update'];
4340

4441
/**
4542
* @inheritDoc
@@ -179,47 +176,6 @@ public function update()
179176
}
180177
}
181178

182-
/**
183-
* @inheritDoc
184-
*/
185-
public function validateUpdatePosition()
186-
{
187-
// validate permissions
188-
if ($this->permissionsUpdate !== []) {
189-
WCF::getSession()->checkPermissions($this->permissionsUpdate);
190-
} else {
191-
throw new PermissionDeniedException();
192-
}
193-
194-
if (!isset($this->parameters['data']['structure'])) {
195-
throw new UserInputException('structure');
196-
}
197-
198-
$this->readInteger('offset', true, 'data');
199-
}
200-
201-
/**
202-
* @inheritDoc
203-
*/
204-
public function updatePosition()
205-
{
206-
$reactionTypeList = new ReactionTypeList();
207-
$reactionTypeList->readObjects();
208-
209-
$i = $this->parameters['data']['offset'];
210-
WCF::getDB()->beginTransaction();
211-
foreach ($this->parameters['data']['structure'][0] as $reactionTypeID) {
212-
$reactionType = $reactionTypeList->search($reactionTypeID);
213-
if ($reactionType === null) {
214-
continue;
215-
}
216-
217-
$editor = new ReactionTypeEditor($reactionType);
218-
$editor->update(['showOrder' => $i++]);
219-
}
220-
WCF::getDB()->commitTransaction();
221-
}
222-
223179
/**
224180
* @inheritDoc
225181
*/
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\gridView\admin;
4+
5+
use wcf\event\IPsr14Event;
6+
use wcf\system\gridView\admin\ReactionTypeGridView;
7+
8+
/**
9+
* Indicates that the reaction type grid view has been initialized.
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 ReactionTypeGridViewInitialized implements IPsr14Event
17+
{
18+
public function __construct(public readonly ReactionTypeGridView $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\admin;
4+
5+
use wcf\event\IPsr14Event;
6+
use wcf\system\interaction\admin\ReactionTypeInteractions;
7+
8+
/**
9+
* Indicates that the provider for reaction type 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 ReactionTypeInteractionCollecting implements IPsr14Event
17+
{
18+
public function __construct(public readonly ReactionTypeInteractions $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\ReactionTypeBulkInteractions;
7+
8+
/**
9+
* Indicates that the provider for reaction type 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 ReactionTypeBulkInteractionCollecting implements IPsr14Event
17+
{
18+
public function __construct(public readonly ReactionTypeBulkInteractions $param)
19+
{
20+
}
21+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
3+
namespace wcf\system\endpoint\controller\core\reactions\types;
4+
5+
use Laminas\Diactoros\Response\JsonResponse;
6+
use Psr\Http\Message\ResponseInterface;
7+
use Psr\Http\Message\ServerRequestInterface;
8+
use wcf\data\reaction\type\ReactionType;
9+
use wcf\data\reaction\type\ReactionTypeAction;
10+
use wcf\http\Helper;
11+
use wcf\system\endpoint\IController;
12+
use wcf\system\endpoint\PostRequest;
13+
use wcf\system\exception\IllegalLinkException;
14+
use wcf\system\exception\PermissionDeniedException;
15+
use wcf\system\WCF;
16+
17+
/**
18+
* API endpoint for setting a reaction type as assignable.
19+
*
20+
* @author Olaf Braun
21+
* @copyright 2001-2025 WoltLab GmbH
22+
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
23+
* @since 6.2
24+
*/
25+
#[PostRequest("/core/reactions/types/{id:\d+}/assignable")]
26+
final class Assignable implements IController
27+
{
28+
public function __invoke(ServerRequestInterface $request, array $variables): ResponseInterface
29+
{
30+
$reactionType = Helper::fetchObjectFromRequestParameter($variables['id'], ReactionType::class);
31+
32+
$this->assertReactionTypeCanBeEnabled($reactionType);
33+
34+
(new ReactionTypeAction([$reactionType], 'toggle'))->executeAction();
35+
36+
return new JsonResponse([]);
37+
}
38+
39+
private function assertReactionTypeCanBeEnabled(ReactionType $reactionType): void
40+
{
41+
if (!\MODULE_LIKE) {
42+
throw new IllegalLinkException();
43+
}
44+
45+
WCF::getSession()->checkPermissions(["admin.content.reaction.canManageReactionType"]);
46+
47+
if ($reactionType->isAssignable) {
48+
throw new PermissionDeniedException();
49+
}
50+
}
51+
}

0 commit comments

Comments
 (0)