From 725a21b02721f92ed0420ed3f807ee921de77992 Mon Sep 17 00:00:00 2001 From: tobi <31960611+tsmethurst@users.noreply.github.com> Date: Wed, 1 May 2024 15:11:22 +0200 Subject: [feature] Page through accounts as moderator (#2881) * [feature] Page through accounts as moderator * aaaaa * use COLLATE "C" for Postgres to ensure same ordering as SQLite * fix typo, test paging up * don't show moderation / info for our instance acct --- web/source/settings/components/pageable-list.tsx | 113 +++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 web/source/settings/components/pageable-list.tsx (limited to 'web/source/settings/components/pageable-list.tsx') diff --git a/web/source/settings/components/pageable-list.tsx b/web/source/settings/components/pageable-list.tsx new file mode 100644 index 000000000..918103ead --- /dev/null +++ b/web/source/settings/components/pageable-list.tsx @@ -0,0 +1,113 @@ +/* + GoToSocial + Copyright (C) GoToSocial Authors admin@gotosocial.org + SPDX-License-Identifier: AGPL-3.0-or-later + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +import React, { ReactNode } from "react"; +import { useLocation } from "wouter"; +import { Error } from "./error"; +import { SerializedError } from "@reduxjs/toolkit"; +import { FetchBaseQueryError } from "@reduxjs/toolkit/query"; +import { Links } from "parse-link-header"; +import Loading from "./loading"; + +export interface PageableListProps { + isSuccess: boolean; + items?: T[]; + itemToEntry: (_item: T) => ReactNode; + isLoading: boolean; + isFetching: boolean; + isError: boolean; + error: FetchBaseQueryError | SerializedError | undefined; + emptyMessage: string; + prevNextLinks?: Links | null | undefined; +} + +export function PageableList({ + isLoading, + isFetching, + isSuccess, + items, + itemToEntry, + isError, + error, + emptyMessage, + prevNextLinks, +}: PageableListProps) { + const [ location, setLocation ] = useLocation(); + + if (!(isSuccess || isError)) { + // Hasn't been called yet. + return null; + } + + if (isLoading || isFetching) { + return ; + } + + if (error) { + return ; + } + + // Map response to items if possible. + let content: ReactNode; + if (items == undefined || items.length == 0) { + content = {emptyMessage}; + } else { + content = ( +
+ {items.map(item => itemToEntry(item))} +
+ ); + } + + // If it's possible to page to next and previous + // pages, instantiate button handlers for this. + let prevClick: (() => void) | undefined; + let nextClick: (() => void) | undefined; + if (prevNextLinks) { + const prev = prevNextLinks["prev"]; + if (prev) { + const prevUrl = new URL(prev.url); + const prevParams = prevUrl.search; + prevClick = () => { + setLocation(location + prevParams.toString()); + }; + } + + const next = prevNextLinks["next"]; + if (next) { + const nextUrl = new URL(next.url); + const nextParams = nextUrl.search; + nextClick = () => { + setLocation(location + nextParams.toString()); + }; + } + } + + return ( +
+ { content } + { prevNextLinks && +
+ { prevClick && } + { nextClick && } +
+ } +
+ ); +} -- cgit v1.2.3