diff --git a/acptemplates/discordBotList.tpl b/acptemplates/discordBotList.tpl
index 88ec652..b3bc7a8 100644
--- a/acptemplates/discordBotList.tpl
+++ b/acptemplates/discordBotList.tpl
@@ -2,7 +2,7 @@
-{hascontent}
-
-{/hascontent}
-
-{if $objects|count}
-
-
-
-{else}
- {lang}wcf.global.noItems{/lang}
-{/if}
+
+ {unsafe:$gridView->render()}
+
{include file='footer'}
\ No newline at end of file
diff --git a/files/lib/acp/page/DiscordBotListPage.class.php b/files/lib/acp/page/DiscordBotListPage.class.php
index daf1977..f64ab06 100644
--- a/files/lib/acp/page/DiscordBotListPage.class.php
+++ b/files/lib/acp/page/DiscordBotListPage.class.php
@@ -2,18 +2,15 @@
namespace wcf\acp\page;
-use wcf\data\discord\bot\DiscordBotList;
-use wcf\page\SortablePage;
+use Override;
+use wcf\page\AbstractGridViewPage;
+use wcf\system\gridView\AbstractGridView;
+use wcf\system\gridView\DiscordBotListGridView;
/**
- * Übersicht aller Discord-Bots
- *
- * @author Peter Lohse
- * @copyright Hanashi
- * @license Freie Lizenz (https://hanashi.dev/freie-lizenz/)
- * @package WoltLabSuite\Core\Acp\Page
+ * @property DiscordBotListGridView $gridView
*/
-class DiscordBotListPage extends SortablePage
+class DiscordBotListPage extends AbstractGridViewPage
{
/**
* @inheritDoc
@@ -25,23 +22,9 @@ class DiscordBotListPage extends SortablePage
*/
public $activeMenuItem = 'wcf.acp.menu.link.configuration.discord.discordBotList';
- /**
- * @inheritDoc
- */
- public $objectListClassName = DiscordBotList::class;
-
- /**
- * @inheritDoc
- */
- public $defaultSortField = 'botID';
-
- /**
- * @inheritDoc
- */
- public $defaultSortOrder = 'ASC';
-
- /**
- * @inheritDoc
- */
- public $validSortFields = ['botID', 'botName', 'guildID', 'guildName', 'botTime'];
+ #[Override]
+ protected function createGridViewController(): AbstractGridView
+ {
+ return new DiscordBotListGridView();
+ }
}
diff --git a/files/lib/bootstrap/dev.hanashi.wsc.discord-api.php b/files/lib/bootstrap/dev.hanashi.wsc.discord-api.php
index 725d164..395e13f 100644
--- a/files/lib/bootstrap/dev.hanashi.wsc.discord-api.php
+++ b/files/lib/bootstrap/dev.hanashi.wsc.discord-api.php
@@ -5,7 +5,9 @@
use wcf\acp\page\DiscordWebhookListPage;
use wcf\event\acp\dashboard\box\PHPExtensionCollecting;
use wcf\event\acp\menu\item\ItemCollecting;
+use wcf\event\endpoint\ControllerCollecting;
use wcf\event\worker\RebuildWorkerCollecting;
+use wcf\system\endpoint\controller\hanashi\discord\bot\DeleteBot;
use wcf\system\event\EventHandler;
use wcf\system\menu\acp\AcpMenuItem;
use wcf\system\request\LinkHandler;
@@ -77,4 +79,11 @@ static function (RebuildWorkerCollecting $event) {
$event->register(DiscordWebhookAvatarRebuildDataWorker::class, 0);
}
);
+
+ EventHandler::getInstance()->register(
+ ControllerCollecting::class,
+ static function (ControllerCollecting $event) {
+ $event->register(new DeleteBot());
+ }
+ );
};
diff --git a/files/lib/data/discord/bot/DiscordBot.class.php b/files/lib/data/discord/bot/DiscordBot.class.php
index 8e71183..24ad250 100644
--- a/files/lib/data/discord/bot/DiscordBot.class.php
+++ b/files/lib/data/discord/bot/DiscordBot.class.php
@@ -2,8 +2,10 @@
namespace wcf\data\discord\bot;
+use Override;
use wcf\data\DatabaseObject;
use wcf\data\file\File;
+use wcf\data\ITitledObject;
use wcf\system\cache\builder\DiscordGuildChannelCacheBuilder;
use wcf\system\discord\DiscordApi;
use wcf\system\WCF;
@@ -29,7 +31,7 @@
* @property-read int $botTime
* @property-read int|null $webhookIconID
*/
-final class DiscordBot extends DatabaseObject
+final class DiscordBot extends DatabaseObject implements ITitledObject
{
/**
* @inheritDoc
@@ -45,6 +47,12 @@ final class DiscordBot extends DatabaseObject
protected ?File $file;
+ #[Override]
+ public function getTitle(): string
+ {
+ return $this->botName;
+ }
+
public function getDiscordApi(): DiscordApi
{
if (!isset($this->discordApi)) {
diff --git a/files/lib/system/endpoint/controller/hanashi/discord/bot/DeleteBot.class.php b/files/lib/system/endpoint/controller/hanashi/discord/bot/DeleteBot.class.php
new file mode 100644
index 0000000..bca7087
--- /dev/null
+++ b/files/lib/system/endpoint/controller/hanashi/discord/bot/DeleteBot.class.php
@@ -0,0 +1,31 @@
+checkPermissions(['admin.discord.canManageConnection']);
+
+ $action = new DiscordBotAction([$bot], 'delete');
+ $action->executeAction();
+
+ return new JsonResponse([]);
+ }
+}
diff --git a/files/lib/system/event/gridView/DiscordBotListGridViewInitialized.class.php b/files/lib/system/event/gridView/DiscordBotListGridViewInitialized.class.php
new file mode 100644
index 0000000..290c036
--- /dev/null
+++ b/files/lib/system/event/gridView/DiscordBotListGridViewInitialized.class.php
@@ -0,0 +1,13 @@
+addColumns([
+ GridViewColumn::for('botID')
+ ->label('wcf.global.objectID')
+ ->renderer(new NumberColumnRenderer())
+ ->sortable(),
+ GridViewColumn::for('botName')
+ ->label('wcf.acp.discordBotList.botName')
+ ->renderer(new TitleColumnRenderer())
+ ->sortable()
+ ->filter(new TextFilter()),
+ GridViewColumn::for('guildName')
+ ->label('wcf.acp.discordBotList.server')
+ ->renderer([
+ new class extends DefaultColumnRenderer {
+ public function render(mixed $value, mixed $context = null): string
+ {
+ \assert($context instanceof DiscordBot);
+
+ $content = '';
+ if (!empty($context->guildIcon)) {
+ $content = \sprintf(
+ '
',
+ $context->guildID,
+ $context->guildIcon
+ );
+ }
+
+ return $content . $context->guildName;
+ }
+ },
+ ])
+ ->sortable()
+ ->filter(new TextFilter()),
+ GridViewColumn::for('botTime')
+ ->label('wcf.global.date')
+ ->renderer(new TimeColumnRenderer())
+ ->sortable()
+ ->filter(new TimeFilter()),
+ ]);
+
+ $this->addActions([
+ new EditAction(DiscordBotEditForm::class),
+ new DeleteAction('hanashi/discord/bot/%s'),
+ ]);
+ $this->setSortField('botID');
+ $this->setSortOrder('ASC');
+ }
+
+ #[Override]
+ public function isAccessible(): bool
+ {
+ return WCF::getSession()->getPermission('admin.discord.canManageConnection');
+ }
+
+ #[Override]
+ protected function createObjectList(): DatabaseObjectList
+ {
+ return new DiscordBotList();
+ }
+
+ #[Override]
+ protected function getInitializedEvent(): ?IPsr14Event
+ {
+ return new DiscordBotListGridViewInitialized($this);
+ }
+}