From: Marcel Werk Date: Tue, 17 Dec 2024 13:31:28 +0000 (+0100) Subject: Add option to refresh a single row X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=b39c6e0709349e59404e8fedcd4be993394a8d35;p=GitHub%2FWoltLab%2FWCF.git Add option to refresh a single row --- diff --git a/ts/WoltLabSuite/Core/Api/Gridviews/GetRow.ts b/ts/WoltLabSuite/Core/Api/Gridviews/GetRow.ts new file mode 100644 index 0000000000..1e23d9fb51 --- /dev/null +++ b/ts/WoltLabSuite/Core/Api/Gridviews/GetRow.ts @@ -0,0 +1,21 @@ +import { prepareRequest } from "WoltLabSuite/Core/Ajax/Backend"; +import { ApiResult, apiResultFromError, apiResultFromValue } from "../Result"; + +type Response = { + template: string; +}; + +export async function getRow(gridViewClass: string, objectId: string | number): Promise> { + const url = new URL(`${window.WSC_RPC_API_URL}core/grid-views/row`); + url.searchParams.set("gridView", gridViewClass); + url.searchParams.set("objectID", objectId.toString()); + + let response: Response; + try { + response = (await prepareRequest(url).get().allowCaching().disableLoadingIndicator().fetchAsJson()) as Response; + } catch (e) { + return apiResultFromError(e); + } + + return apiResultFromValue(response); +} diff --git a/ts/WoltLabSuite/Core/Component/GridView.ts b/ts/WoltLabSuite/Core/Component/GridView.ts index a0a82ba9c5..9162951dda 100644 --- a/ts/WoltLabSuite/Core/Component/GridView.ts +++ b/ts/WoltLabSuite/Core/Component/GridView.ts @@ -1,3 +1,4 @@ +import { getRow } from "../Api/Gridviews/GetRow"; import { getRows } from "../Api/Gridviews/GetRows"; import DomChangeListener from "../Dom/Change/Listener"; import DomUtil from "../Dom/Util"; @@ -48,6 +49,7 @@ export class GridView { this.#initSorting(); this.#initActions(); this.#initFilters(); + this.#initEventListeners(); window.addEventListener("popstate", () => { this.#handlePopState(); @@ -129,6 +131,12 @@ export class GridView { this.#initActions(); } + async #refreshRow(row: HTMLElement): Promise { + const response = (await getRow(this.#gridClassName, row.dataset.objectId!)).unwrap(); + row.replaceWith(DomUtil.createFragmentFromHtml(response.template)); + DomChangeListener.trigger(); + } + #updateQueryString(): void { if (!this.#baseUrl) { return; @@ -282,4 +290,10 @@ export class GridView { this.#switchPage(pageNo, false); } + + #initEventListeners(): void { + this.#table.addEventListener("refresh", (event) => { + void this.#refreshRow(event.target as HTMLElement); + }); + } } diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Api/Gridviews/GetRow.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Api/Gridviews/GetRow.js new file mode 100644 index 0000000000..de757a5426 --- /dev/null +++ b/wcfsetup/install/files/js/WoltLabSuite/Core/Api/Gridviews/GetRow.js @@ -0,0 +1,18 @@ +define(["require", "exports", "WoltLabSuite/Core/Ajax/Backend", "../Result"], function (require, exports, Backend_1, Result_1) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.getRow = getRow; + async function getRow(gridViewClass, objectId) { + const url = new URL(`${window.WSC_RPC_API_URL}core/grid-views/row`); + url.searchParams.set("gridView", gridViewClass); + url.searchParams.set("objectID", objectId.toString()); + let response; + try { + response = (await (0, Backend_1.prepareRequest)(url).get().allowCaching().disableLoadingIndicator().fetchAsJson()); + } + catch (e) { + return (0, Result_1.apiResultFromError)(e); + } + return (0, Result_1.apiResultFromValue)(response); + } +}); diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Component/GridView.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Component/GridView.js index addb5e72bd..d2ac3e8f5d 100644 --- a/wcfsetup/install/files/js/WoltLabSuite/Core/Component/GridView.js +++ b/wcfsetup/install/files/js/WoltLabSuite/Core/Component/GridView.js @@ -1,4 +1,4 @@ -define(["require", "exports", "tslib", "../Api/Gridviews/GetRows", "../Dom/Change/Listener", "../Dom/Util", "../Helper/PromiseMutex", "../Ui/Dropdown/Simple", "./Dialog"], function (require, exports, tslib_1, GetRows_1, Listener_1, Util_1, PromiseMutex_1, Simple_1, Dialog_1) { +define(["require", "exports", "tslib", "../Api/Gridviews/GetRow", "../Api/Gridviews/GetRows", "../Dom/Change/Listener", "../Dom/Util", "../Helper/PromiseMutex", "../Ui/Dropdown/Simple", "./Dialog"], function (require, exports, tslib_1, GetRow_1, GetRows_1, Listener_1, Util_1, PromiseMutex_1, Simple_1, Dialog_1) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.GridView = void 0; @@ -38,6 +38,7 @@ define(["require", "exports", "tslib", "../Api/Gridviews/GetRows", "../Dom/Chang this.#initSorting(); this.#initActions(); this.#initFilters(); + this.#initEventListeners(); window.addEventListener("popstate", () => { this.#handlePopState(); }); @@ -95,6 +96,11 @@ define(["require", "exports", "tslib", "../Api/Gridviews/GetRows", "../Dom/Chang this.#renderFilters(response.filterLabels); this.#initActions(); } + async #refreshRow(row) { + const response = (await (0, GetRow_1.getRow)(this.#gridClassName, row.dataset.objectId)).unwrap(); + row.replaceWith(Util_1.default.createFragmentFromHtml(response.template)); + Listener_1.default.trigger(); + } #updateQueryString() { if (!this.#baseUrl) { return; @@ -219,6 +225,11 @@ define(["require", "exports", "tslib", "../Api/Gridviews/GetRows", "../Dom/Chang }); this.#switchPage(pageNo, false); } + #initEventListeners() { + this.#table.addEventListener("refresh", (event) => { + void this.#refreshRow(event.target); + }); + } } exports.GridView = GridView; }); diff --git a/wcfsetup/install/files/lib/bootstrap/com.woltlab.wcf.php b/wcfsetup/install/files/lib/bootstrap/com.woltlab.wcf.php index 60ddb452b2..c4410b5469 100644 --- a/wcfsetup/install/files/lib/bootstrap/com.woltlab.wcf.php +++ b/wcfsetup/install/files/lib/bootstrap/com.woltlab.wcf.php @@ -136,6 +136,7 @@ return static function (): void { $event->register(new \wcf\system\endpoint\controller\core\comments\responses\UpdateResponse); $event->register(new \wcf\system\endpoint\controller\core\exceptions\RenderException); $event->register(new \wcf\system\endpoint\controller\core\gridViews\GetRows); + $event->register(new \wcf\system\endpoint\controller\core\gridViews\GetRow); $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); diff --git a/wcfsetup/install/files/lib/system/endpoint/controller/core/gridViews/GetRow.class.php b/wcfsetup/install/files/lib/system/endpoint/controller/core/gridViews/GetRow.class.php new file mode 100644 index 0000000000..ded963e765 --- /dev/null +++ b/wcfsetup/install/files/lib/system/endpoint/controller/core/gridViews/GetRow.class.php @@ -0,0 +1,58 @@ + + * @since 6.2 + */ +#[GetRequest('/core/grid-views/row')] +final class GetRow implements IController +{ + #[\Override] + public function __invoke(ServerRequestInterface $request, array $variables): ResponseInterface + { + $parameters = Helper::mapApiParameters($request, GetRowParameters::class); + + if (!\is_subclass_of($parameters->gridView, AbstractGridView::class)) { + throw new UserInputException('gridView', 'invalid'); + } + + $view = new $parameters->gridView(); + \assert($view instanceof AbstractGridView); + + if (!$view->isAccessible()) { + throw new PermissionDeniedException(); + } + + $view->setObjectIDFilter($parameters->objectID); + + return new JsonResponse([ + 'template' => $view->renderRows(), + ]); + } +} + +/** @internal */ +final class GetRowParameters +{ + public function __construct( + /** @var non-empty-string */ + public readonly string $gridView, + public readonly string|int $objectID, + ) {} +} diff --git a/wcfsetup/install/files/lib/system/gridView/AbstractGridView.class.php b/wcfsetup/install/files/lib/system/gridView/AbstractGridView.class.php index 8486986558..71add3162b 100644 --- a/wcfsetup/install/files/lib/system/gridView/AbstractGridView.class.php +++ b/wcfsetup/install/files/lib/system/gridView/AbstractGridView.class.php @@ -38,6 +38,7 @@ abstract class AbstractGridView private string $sortOrder = 'ASC'; private int $pageNo = 1; private array $activeFilters = []; + private string|int|null $objectIDFilter = null; /** * Adds a new column to the grid view. @@ -487,6 +488,16 @@ abstract class AbstractGridView return ''; } + public function setObjectIDFilter(string|int|null $objectID): void + { + $this->objectIDFilter = $objectID; + } + + public function getObjectIDFilter(): string|int|null + { + return $this->objectIDFilter; + } + /** * Fires the initialized event. */ diff --git a/wcfsetup/install/files/lib/system/gridView/DatabaseObjectListGridView.class.php b/wcfsetup/install/files/lib/system/gridView/DatabaseObjectListGridView.class.php index 55218b8cc0..9c41b03a62 100644 --- a/wcfsetup/install/files/lib/system/gridView/DatabaseObjectListGridView.class.php +++ b/wcfsetup/install/files/lib/system/gridView/DatabaseObjectListGridView.class.php @@ -72,6 +72,12 @@ abstract class DatabaseObjectListGridView extends AbstractGridView $this->objectList->sqlOrderBy .= ',' . $this->objectList->getDatabaseTableAlias() . '.' . $this->objectList->getDatabaseTableIndexName() . ' ' . $this->getSortOrder(); } + if ($this->getObjectIDFilter() !== null) { + $this->objectList->getConditionBuilder()->add( + $this->objectList->getDatabaseTableAlias() . '.' . $this->objectList->getDatabaseTableIndexName() . ' = ?', + [$this->getObjectIDFilter()] + ); + } $this->applyFilters(); $this->validate(); $this->fireInitializedEvent();