From dd3458c416404811b7168f0c73aa99ef61d72ff9 Mon Sep 17 00:00:00 2001 From: Marcel Werk Date: Mon, 9 Sep 2024 15:18:53 +0200 Subject: [PATCH] Grid view (PoC) See #5967 --- com.woltlab.wcf/templates/shared_gridView.tpl | 31 +++++ ts/WoltLabSuite/Core/Api/GridViews/GetRows.ts | 21 +++ ts/WoltLabSuite/Core/Component/GridView.ts | 61 ++++++++ .../files/acp/templates/userRankList.tpl | 6 +- .../Core/Api/GridViews/GetRows.js | 19 +++ .../WoltLabSuite/Core/Component/GridView.js | 55 ++++++++ .../lib/acp/page/UserRankListPage.class.php | 15 ++ .../files/lib/bootstrap/com.woltlab.wcf.php | 1 + .../core/gridViews/GetRows.class.php | 48 +++++++ .../view/grid/AbstractGridView.class.php | 130 ++++++++++++++++++ .../system/view/grid/GridViewColumn.class.php | 101 ++++++++++++++ .../view/grid/UserRankGridView.class.php | 108 +++++++++++++++ .../renderer/AbstractColumnRenderer.class.php | 11 ++ .../renderer/DefaultColumnRenderer.class.php | 18 +++ .../grid/renderer/IColumnRenderer.class.php | 10 ++ .../renderer/LinkColumnRenderer.class.php | 31 +++++ .../renderer/NumberColumnRenderer.class.php | 18 +++ .../renderer/TitleColumnRenderer.class.php | 11 ++ 18 files changed, 693 insertions(+), 2 deletions(-) create mode 100644 com.woltlab.wcf/templates/shared_gridView.tpl create mode 100644 ts/WoltLabSuite/Core/Api/GridViews/GetRows.ts create mode 100644 ts/WoltLabSuite/Core/Component/GridView.ts create mode 100644 wcfsetup/install/files/js/WoltLabSuite/Core/Api/GridViews/GetRows.js create mode 100644 wcfsetup/install/files/js/WoltLabSuite/Core/Component/GridView.js create mode 100644 wcfsetup/install/files/lib/system/endpoint/controller/core/gridViews/GetRows.class.php create mode 100644 wcfsetup/install/files/lib/system/view/grid/AbstractGridView.class.php create mode 100644 wcfsetup/install/files/lib/system/view/grid/GridViewColumn.class.php create mode 100644 wcfsetup/install/files/lib/system/view/grid/UserRankGridView.class.php create mode 100644 wcfsetup/install/files/lib/system/view/grid/renderer/AbstractColumnRenderer.class.php create mode 100644 wcfsetup/install/files/lib/system/view/grid/renderer/DefaultColumnRenderer.class.php create mode 100644 wcfsetup/install/files/lib/system/view/grid/renderer/IColumnRenderer.class.php create mode 100644 wcfsetup/install/files/lib/system/view/grid/renderer/LinkColumnRenderer.class.php create mode 100644 wcfsetup/install/files/lib/system/view/grid/renderer/NumberColumnRenderer.class.php create mode 100644 wcfsetup/install/files/lib/system/view/grid/renderer/TitleColumnRenderer.class.php diff --git a/com.woltlab.wcf/templates/shared_gridView.tpl b/com.woltlab.wcf/templates/shared_gridView.tpl new file mode 100644 index 0000000000..8c63d1f10a --- /dev/null +++ b/com.woltlab.wcf/templates/shared_gridView.tpl @@ -0,0 +1,31 @@ +
+ +
+ +
+ + + + {unsafe:$view->renderHeader()} + + + + {unsafe:$view->renderRows()} + +
+
+ +
+ +
+ + diff --git a/ts/WoltLabSuite/Core/Api/GridViews/GetRows.ts b/ts/WoltLabSuite/Core/Api/GridViews/GetRows.ts new file mode 100644 index 0000000000..f84280e050 --- /dev/null +++ b/ts/WoltLabSuite/Core/Api/GridViews/GetRows.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 getRows(gridViewClass: string, pageNo: number): Promise> { + const url = new URL(`${window.WSC_RPC_API_URL}core/gridViews/rows`); + url.searchParams.set("gridView", gridViewClass); + url.searchParams.set("pageNo", pageNo.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 new file mode 100644 index 0000000000..73e184bd28 --- /dev/null +++ b/ts/WoltLabSuite/Core/Component/GridView.ts @@ -0,0 +1,61 @@ +import { getRows } from "../Api/GridViews/GetRows"; +import DomUtil from "../Dom/Util"; + +export class GridView { + readonly #gridClassName: string; + readonly #table: HTMLTableElement; + readonly #topPagination: WoltlabCorePaginationElement; + readonly #bottomPagination: WoltlabCorePaginationElement; + readonly #baseUrl: string; + #pageNo: number; + + constructor(gridId: string, gridClassName: string, pageNo: number, baseUrl: string = "") { + this.#gridClassName = gridClassName; + this.#table = document.getElementById(`${gridId}_table`) as HTMLTableElement; + this.#topPagination = document.getElementById(`${gridId}_topPagination`) as WoltlabCorePaginationElement; + this.#bottomPagination = document.getElementById(`${gridId}_bottomPagination`) as WoltlabCorePaginationElement; + this.#pageNo = pageNo; + this.#baseUrl = baseUrl; + + this.#initPagination(); + } + + #initPagination(): void { + this.#topPagination.addEventListener("switchPage", (event: CustomEvent) => { + this.#switchPage(event.detail); + }); + this.#bottomPagination.addEventListener("switchPage", (event: CustomEvent) => { + this.#switchPage(event.detail); + }); + } + + async #switchPage(pageNo: number): Promise { + this.#topPagination.page = pageNo; + this.#bottomPagination.page = pageNo; + + const response = await getRows(this.#gridClassName, pageNo); + this.#pageNo = pageNo; + DomUtil.setInnerHtml(this.#table.querySelector("tbody")!, response.unwrap().template); + this.#updateQueryString(); + } + + #updateQueryString(): void { + if (!this.#baseUrl) { + return; + } + + const url = new URL(this.#baseUrl); + + const parameters: [string, string][] = []; + if (this.#pageNo > 1) { + parameters.push(["pageNo", this.#pageNo.toString()]); + } + + if (parameters.length > 0) { + url.search += url.search !== "" ? "&" : "?"; + url.search += new URLSearchParams(parameters).toString(); + } + + window.history.pushState({ name: "gridView" }, document.title, url.toString()); + } +} diff --git a/wcfsetup/install/files/acp/templates/userRankList.tpl b/wcfsetup/install/files/acp/templates/userRankList.tpl index b9dbcbce21..8fabc66d57 100644 --- a/wcfsetup/install/files/acp/templates/userRankList.tpl +++ b/wcfsetup/install/files/acp/templates/userRankList.tpl @@ -39,7 +39,9 @@ {/hascontent} {if $objects|count} -
+ {unsafe:$view->render()} + + {*
@@ -85,7 +87,7 @@ {/foreach}
-
+
*}