Skip to content

Commit

Permalink
Migration user option list to grid view
Browse files Browse the repository at this point in the history
  • Loading branch information
BurntimeX committed Nov 12, 2024
1 parent f4d3e02 commit c9e9a97
Show file tree
Hide file tree
Showing 12 changed files with 355 additions and 132 deletions.
71 changes: 2 additions & 69 deletions wcfsetup/install/files/acp/templates/userOptionList.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.user.option.list{/lang} <span class="badge badgeInverse">{#$items}</span></h1>
<h1 class="contentTitle">{lang}wcf.acp.user.option.list{/lang} <span class="badge badgeInverse">{#$gridView->countRows()}</span></h1>
</div>

<nav class="contentHeaderNavigation">
Expand All @@ -14,73 +14,6 @@
</nav>
</header>

{hascontent}
<div class="paginationTop">
{content}{pages print=true assign=pagesLinks controller="UserOptionList" 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\user\option\UserOptionAction">
<thead>
<tr>
<th class="columnID columnOptionID{if $sortField == 'optionID'} active {@$sortOrder}{/if}" colspan="2"><a href="{link controller='UserOptionList'}pageNo={@$pageNo}&sortField=optionID&sortOrder={if $sortField == 'optionID' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{/link}">{lang}wcf.global.objectID{/lang}</a></th>
<th class="columnTitle columnOptionName{if $sortField == 'optionName'} active {@$sortOrder}{/if}"><a href="{link controller='UserOptionList'}pageNo={@$pageNo}&sortField=optionName&sortOrder={if $sortField == 'optionName' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{/link}">{lang}wcf.global.name{/lang}</a></th>
<th class="columnText columnCategoryName{if $sortField == 'categoryName'} active {@$sortOrder}{/if}"><a href="{link controller='UserOptionList'}pageNo={@$pageNo}&sortField=categoryName&sortOrder={if $sortField == 'categoryName' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{/link}">{lang}wcf.global.category{/lang}</a></th>
<th class="columnText columnOptionType{if $sortField == 'optionType'} active {@$sortOrder}{/if}"><a href="{link controller='UserOptionList'}pageNo={@$pageNo}&sortField=optionType&sortOrder={if $sortField == 'optionType' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{/link}">{lang}wcf.acp.user.option.optionType{/lang}</a></th>
<th class="columnDigits columnShowOrder{if $sortField == 'showOrder'} active {@$sortOrder}{/if}"><a href="{link controller='UserOptionList'}pageNo={@$pageNo}&sortField=showOrder&sortOrder={if $sortField == 'showOrder' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{/link}">{lang}wcf.global.showOrder{/lang}</a></th>

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

<tbody class="jsReloadPageWhenEmpty">
{foreach from=$objects item=option}
<tr class="jsOptionRow jsObjectActionObject" data-object-id="{@$option->getObjectID()}">
<td class="columnIcon">
{objectAction action="toggle" isDisabled=$option->isDisabled}
<a href="{link controller='UserOptionEdit' id=$option->optionID}{/link}" title="{lang}wcf.global.button.edit{/lang}" class="jsTooltip">{icon name='pencil'}</a>
{if $option->canDelete()}
{objectAction action="delete" objectTitle=$option->getTitle()}
{else}
<span class="disabled" title="{lang}wcf.global.button.delete{/lang}">
{icon name='xmark'}
</span>
{/if}

{event name='rowButtons'}
</td>
<td class="columnID">{@$option->optionID}</td>
<td class="columnTitle columnOptionName"><a href="{link controller='UserOptionEdit' id=$option->optionID}{/link}">{$option->getTitle()}</a></td>
<td class="columnText columnCategoryName">{lang}wcf.user.option.category.{$option->categoryName}{/lang}</td>
<td class="columnText columnOptionType">{$option->optionType}</td>
<td class="columnDigits columnShowOrder">{#$option->showOrder}</td>

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

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

<nav class="contentFooterNavigation">
<ul>
<li><a href="{link controller='UserOptionAdd'}{/link}" class="button">{icon name='plus'} <span>{lang}wcf.acp.user.option.add{/lang}</span></a></li>

{event name='contentFooterNavigation'}
</ul>
</nav>
</footer>
{else}
<woltlab-core-notice type="info">{lang}wcf.global.noItems{/lang}</woltlab-core-notice>
{/if}
{unsafe:$gridView->render()}

{include file='footer'}
49 changes: 12 additions & 37 deletions wcfsetup/install/files/lib/acp/page/UserOptionListPage.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,20 @@

namespace wcf\acp\page;

use wcf\data\user\option\UserOptionList;
use wcf\page\SortablePage;
use wcf\page\AbstractGridViewPage;
use wcf\system\view\grid\AbstractGridView;
use wcf\system\view\grid\UserOptionGridView;

/**
* Shows a list of installed user options.
* Shows a list of the installed user options.
*
* @author Marcel Werk
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
* @author Marcel Werk
* @copyright 2001-2024 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
*
* @property UserOptionList $objectList
* @property UserOptionGridView $gridView
*/
class UserOptionListPage extends SortablePage
class UserOptionListPage extends AbstractGridViewPage
{
/**
* @inheritDoc
Expand All @@ -26,35 +27,9 @@ class UserOptionListPage extends SortablePage
*/
public $neededPermissions = ['admin.user.canManageUserOption'];

/**
* @inheritDoc
*/
public $defaultSortField = 'showOrder';

/**
* @inheritDoc
*/
public $objectListClassName = UserOptionList::class;

/**
* @inheritDoc
*/
public $validSortFields = ['optionID', 'optionName', 'categoryName', 'optionType', 'showOrder'];

/**
* @inheritDoc
*/
protected function initObjectList()
#[\Override]
protected function createGridViewController(): AbstractGridView
{
parent::initObjectList();

$this->objectList->getConditionBuilder()->add(
"option_table.categoryName IN (
SELECT categoryName
FROM wcf1_user_option_category
WHERE parentCategoryName = ?
)",
['profile']
);
return new UserOptionGridView();
}
}
3 changes: 3 additions & 0 deletions wcfsetup/install/files/lib/bootstrap/com.woltlab.wcf.php
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,9 @@ static function (\wcf\event\endpoint\ControllerCollecting $event) {
$event->register(new \wcf\system\endpoint\controller\core\gridViews\GetRows);
$event->register(new \wcf\system\endpoint\controller\core\messages\GetMentionSuggestions);
$event->register(new \wcf\system\endpoint\controller\core\sessions\DeleteSession);
$event->register(new \wcf\system\endpoint\controller\core\users\options\DeleteOption);
$event->register(new \wcf\system\endpoint\controller\core\users\options\DisableOption);
$event->register(new \wcf\system\endpoint\controller\core\users\options\EnableOption);
$event->register(new \wcf\system\endpoint\controller\core\users\ranks\DeleteUserRank);
}
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@
namespace wcf\data\user\option;

use wcf\data\AbstractDatabaseObjectAction;
use wcf\data\IToggleAction;
use wcf\data\TDatabaseObjectToggle;
use wcf\system\exception\PermissionDeniedException;

/**
* Executes user option-related actions.
Expand All @@ -18,10 +15,8 @@
* @method UserOptionEditor[] getObjects()
* @method UserOptionEditor getSingleObject()
*/
class UserOptionAction extends AbstractDatabaseObjectAction implements IToggleAction
class UserOptionAction extends AbstractDatabaseObjectAction
{
use TDatabaseObjectToggle;

/**
* @inheritDoc
*/
Expand All @@ -32,11 +27,6 @@ class UserOptionAction extends AbstractDatabaseObjectAction implements IToggleAc
*/
protected $permissionsCreate = ['admin.user.canManageUserOption'];

/**
* @inheritDoc
*/
protected $permissionsDelete = ['admin.user.canManageUserOption'];

/**
* @inheritDoc
*/
Expand All @@ -45,19 +35,5 @@ class UserOptionAction extends AbstractDatabaseObjectAction implements IToggleAc
/**
* @inheritDoc
*/
protected $requireACP = ['create', 'delete', 'toggle', 'update'];

/**
* @inheritDoc
*/
public function validateDelete()
{
parent::validateDelete();

foreach ($this->getObjects() as $userOption) {
if (!$userOption->canDelete()) {
throw new PermissionDeniedException();
}
}
}
protected $requireACP = ['create', 'update'];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace wcf\event\gridView;

use wcf\event\IPsr14Event;
use wcf\system\view\grid\UserOptionGridView;

/**
* Indicates that the user option grid view has been initialized.
*
* @author Marcel Werk
* @copyright 2001-2024 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
* @since 6.2
*/
final class UserOptionGridViewInitialized implements IPsr14Event
{
public function __construct(public readonly UserOptionGridView $gridView) {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

namespace wcf\system\endpoint\controller\core\users\options;

use Laminas\Diactoros\Response\JsonResponse;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use wcf\data\user\option\UserOption;
use wcf\http\Helper;
use wcf\system\endpoint\DeleteRequest;
use wcf\system\endpoint\IController;
use wcf\system\exception\PermissionDeniedException;
use wcf\system\WCF;

/**
* API endpoint for deleting user options.
*
* @author Marcel Werk
* @copyright 2001-2024 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
* @since 6.2
*/
#[DeleteRequest('/core/users/options/{id:\d+}')]
final class DeleteOption implements IController
{
#[\Override]
public function __invoke(ServerRequestInterface $request, array $variables): ResponseInterface
{
$option = Helper::fetchObjectFromRequestParameter($variables['id'], UserOption::class);

$this->assertOptionCanBeDeleted($option);

(new \wcf\system\user\option\command\DeleteOption($option))();

return new JsonResponse([]);
}

private function assertOptionCanBeDeleted(UserOption $option): void
{
WCF::getSession()->checkPermissions(['admin.user.canManageUserOption']);

if (!$option->canDelete()) {
throw new PermissionDeniedException();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

namespace wcf\system\endpoint\controller\core\users\options;

use Laminas\Diactoros\Response\JsonResponse;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use wcf\data\user\option\UserOption;
use wcf\http\Helper;
use wcf\system\endpoint\IController;
use wcf\system\endpoint\PostRequest;
use wcf\system\WCF;

/**
* API endpoint for disabling user options.
*
* @author Marcel Werk
* @copyright 2001-2024 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
* @since 6.2
*/
#[PostRequest('/core/users/options/{id:\d+}/disable')]
final class DisableOption implements IController
{
#[\Override]
public function __invoke(ServerRequestInterface $request, array $variables): ResponseInterface
{
$option = Helper::fetchObjectFromRequestParameter($variables['id'], UserOption::class);

$this->assertOptionCanBeDisabled();

if (!$option->isDisabled) {
(new \wcf\system\user\option\command\DisableOption($option))();
}

return new JsonResponse([]);
}

private function assertOptionCanBeDisabled(): void
{
WCF::getSession()->checkPermissions(['admin.user.canManageUserOption']);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

namespace wcf\system\endpoint\controller\core\users\options;

use Laminas\Diactoros\Response\JsonResponse;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use wcf\data\user\option\UserOption;
use wcf\http\Helper;
use wcf\system\endpoint\IController;
use wcf\system\endpoint\PostRequest;
use wcf\system\WCF;

/**
* API endpoint for enabling user options.
*
* @author Marcel Werk
* @copyright 2001-2024 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
* @since 6.2
*/
#[PostRequest('/core/users/options/{id:\d+}/enable')]
final class EnableOption implements IController
{
#[\Override]
public function __invoke(ServerRequestInterface $request, array $variables): ResponseInterface
{
$option = Helper::fetchObjectFromRequestParameter($variables['id'], UserOption::class);

$this->assertOptionCanBeEnabled();

if ($option->isDisabled) {
(new \wcf\system\user\option\command\EnableOption($option))();
}

return new JsonResponse([]);
}

private function assertOptionCanBeEnabled(): void
{
WCF::getSession()->checkPermissions(['admin.user.canManageUserOption']);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace wcf\system\user\option\command;

use wcf\data\user\option\UserOption;
use wcf\data\user\option\UserOptionAction;

/**
* Deletes a user option.
*
* @author Marcel Werk
* @copyright 2001-2024 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
* @since 6.2
*/
final class DeleteOption
{
public function __construct(
private readonly UserOption $option,
) {}

public function __invoke(): void
{
$action = new UserOptionAction([$this->option], 'delete');
$action->executeAction();
}
}
Loading

0 comments on commit c9e9a97

Please sign in to comment.