Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement grid view #187

Draft
wants to merge 6 commits into
base: 2.8
Choose a base branch
from
Draft
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
80 changes: 4 additions & 76 deletions acptemplates/discordBotList.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<header class="contentHeader">
<div class="contentHeaderTitle">
<h1 class="contentTitle">{lang}wcf.acp.menu.link.configuration.discord.discordBotList{/lang}</h1>
<h1 class="contentTitle">{lang}wcf.acp.menu.link.configuration.discord.discordBotList{/lang}{if $gridView->countRows()} <span class="badge badgeInverse">{#$gridView->countRows()}</span>{/if}</h1>
</div>

<nav class="contentHeaderNavigation">
Expand All @@ -13,80 +13,8 @@
</nav>
</header>

{hascontent}
<div class="paginationTop">
{content}
{pages print=true assign=pagesLinks controller='DiscordBotList' link="pageNo=%d&sortField=$sortField&sortOrder=$sortOrder"}
{/content}
</div>
{/hascontent}

{if $objects|count}
<div class="section tabularBox">
<table class="table jsObjectActionContainer" data-object-action-class-name="wcf\data\discord\bot\DiscordBotAction">
<thead>
<tr>
<th class="columnIcon"></th>
<th class="columnID columnBotID{if $sortField == 'botID'} active {$sortOrder}{/if}"><a href="{link controller='DiscordBotList'}pageNo={$pageNo}&sortField=botID&sortOrder={if $sortField == 'botID' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{/link}">{lang}wcf.global.objectID{/lang}</a></th>
<th class="columnTitle columnBotName{if $sortField == 'botName'} active {$sortOrder}{/if}"><a href="{link controller='DiscordBotList'}pageNo={$pageNo}&sortField=botName&sortOrder={if $sortField == 'botName' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{/link}">{lang}wcf.acp.discordBotList.botName{/lang}</a></th>
<th class="columnText columnGuildName{if $sortField == 'guildName'} active {$sortOrder}{/if}"><a href="{link controller='DiscordBotList'}pageNo={$pageNo}&sortField=guildName&sortOrder={if $sortField == 'guildName' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{/link}">{lang}wcf.acp.discordBotList.server{/lang}</a></th>
<th class="columnDate columnBotTime{if $sortField == 'botTime'} active {$sortOrder}{/if}"><a href="{link controller='DiscordBotList'}pageNo={$pageNo}&sortField=botTime&sortOrder={if $sortField == 'botTime' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{/link}">{lang}wcf.global.date{/lang}</a></th>

{event name='columns'}
</tr>
</thead>

<tbody>
{foreach from=$objects item=discordBot}
<tr class="jsObjectActionObject" data-object-id="{$discordBot->botID}">
<td class="columnIcon">
<a href="{link controller='DiscordBotEdit' id=$discordBot->botID}{/link}" title="{lang}wcf.global.button.edit{/lang}" class="jsTooltip">{icon size=16 name='pencil'}</a>
{objectAction action="delete" objectTitle=$discordBot->botName}

{event name='icons'}
</td>
<td class="columnID">
{#$discordBot->botID}
</td>
<td class="columnTitle">
{$discordBot->botName}
</td>
<td class="columnText">
{if !$discordBot->guildIcon|empty}
<img src="https://cdn.discordapp.com/icons/{$discordBot->guildID}/{$discordBot->guildIcon}.png" style="max-width: 32px; border-radius: 50%; margin-right: 10px;">
{/if}
{$discordBot->guildName}
</td>
<td class="columnDate">
{time time=$discordBot->botTime}
</td>

{event name='columnsItem'}
</tr>
{/foreach}
</tbody>
</table>
</div>

<footer class="contentFooter">
{hascontent}
<div class="paginationBottom">
{content}{unsafe:$pagesLinks}{/content}
</div>
{/hascontent}

{hascontent}
<nav class="contentFooterNavigation">
<ul>
{content}
{event name='contentFooterNavigation'}
{/content}
</ul>
</nav>
{/hascontent}
</footer>
{else}
<p class="info">{lang}wcf.global.noItems{/lang}</p>
{/if}
<div class="section">
{unsafe:$gridView->render()}
</div>

{include file='footer'}
39 changes: 11 additions & 28 deletions files/lib/acp/page/DiscordBotListPage.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -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 <hanashi@hanashi.eu>
* @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
Expand All @@ -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();
}
}
9 changes: 9 additions & 0 deletions files/lib/bootstrap/dev.hanashi.wsc.discord-api.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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());
}
);
};
10 changes: 9 additions & 1 deletion files/lib/data/discord/bot/DiscordBot.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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
Expand All @@ -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)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

namespace wcf\system\endpoint\controller\hanashi\discord\bot;

use Laminas\Diactoros\Response\JsonResponse;
use Override;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use wcf\data\discord\bot\DiscordBot;
use wcf\data\discord\bot\DiscordBotAction;
use wcf\http\Helper;
use wcf\system\endpoint\DeleteRequest;
use wcf\system\endpoint\IController;
use wcf\system\WCF;

#[DeleteRequest('/hanashi/discord/bot/{id:\d+}')]
final class DeleteBot implements IController
{
#[Override]
public function __invoke(ServerRequestInterface $request, array $variables): ResponseInterface
{
$bot = Helper::fetchObjectFromRequestParameter($variables['id'], DiscordBot::class);

WCF::getSession()->checkPermissions(['admin.discord.canManageConnection']);

$action = new DiscordBotAction([$bot], 'delete');
$action->executeAction();

return new JsonResponse([]);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace wcf\system\event\gridView;

use wcf\event\IPsr14Event;
use wcf\system\gridView\DiscordBotListGridView;

final class DiscordBotListGridViewInitialized implements IPsr14Event
{
public function __construct(public readonly DiscordBotListGridView $gridView)
{
}
}
94 changes: 94 additions & 0 deletions files/lib/system/gridView/DiscordBotListGridView.class.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<?php

namespace wcf\system\gridView;

use Override;
use wcf\acp\form\DiscordBotEditForm;
use wcf\data\DatabaseObjectList;
use wcf\data\discord\bot\DiscordBot;
use wcf\data\discord\bot\DiscordBotList;
use wcf\event\IPsr14Event;
use wcf\system\event\gridView\DiscordBotListGridViewInitialized;
use wcf\system\gridView\action\DeleteAction;
use wcf\system\gridView\action\EditAction;
use wcf\system\gridView\filter\TextFilter;
use wcf\system\gridView\filter\TimeFilter;
use wcf\system\gridView\renderer\DefaultColumnRenderer;
use wcf\system\gridView\renderer\NumberColumnRenderer;
use wcf\system\gridView\renderer\TimeColumnRenderer;
use wcf\system\gridView\renderer\TitleColumnRenderer;
use wcf\system\WCF;

final class DiscordBotListGridView extends DatabaseObjectListGridView
{
public function __construct()
{
$this->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(
'<img
src="https://cdn.discordapp.com/icons/%s/%s.png"
style="max-width: 32px; border-radius: 50%%; margin-right: 10px;"
>',
$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);
}
}
Loading