Add is-admin filter to Server Admin Console and add a component to show the server admins on side panel

This commit is contained in:
carlosmonastyrski
2025-03-07 11:42:15 -03:00
parent 58ebebb162
commit 214f837041
8 changed files with 197 additions and 17 deletions
@@ -1,6 +1,13 @@
import { useState } from "react";
import { faMagnifyingGlass, faUsers, faEllipsis } from "@fortawesome/free-solid-svg-icons";
import {
faCheckCircle,
faEllipsis,
faFilter,
faMagnifyingGlass,
faUsers
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { twMerge } from "tailwind-merge";
import { UpgradePlanModal } from "@app/components/license/UpgradePlanModal";
import { createNotification } from "@app/components/notifications";
@@ -8,8 +15,15 @@ import {
Badge,
Button,
DeleteActionModal,
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuTrigger,
EmptyState,
IconButton,
Input,
Switch,
Table,
TableContainer,
TableSkeleton,
@@ -17,11 +31,7 @@ import {
Td,
Th,
THead,
Tr,
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger
Tr
} from "@app/components/v2";
import { useSubscription, useUser } from "@app/context";
import { useDebounce, usePopUp } from "@app/hooks";
@@ -48,6 +58,7 @@ const UserPanelTable = ({
) => void;
}) => {
const [searchUserFilter, setSearchUserFilter] = useState("");
const [adminsOnly, setAdminsOnly] = useState(false);
const { user } = useUser();
const userId = user?.id || "";
const [debounedSearchTerm] = useDebounce(searchUserFilter, 500);
@@ -55,18 +66,60 @@ const UserPanelTable = ({
const { data, isPending, isFetchingNextPage, hasNextPage, fetchNextPage } = useAdminGetUsers({
limit: 20,
searchTerm: debounedSearchTerm
searchTerm: debounedSearchTerm,
adminsOnly
});
const isEmpty = !isPending && !data?.pages?.[0].length;
const isTableFiltered = Boolean(adminsOnly);
return (
<>
<Input
value={searchUserFilter}
onChange={(e) => setSearchUserFilter(e.target.value)}
leftIcon={<FontAwesomeIcon icon={faMagnifyingGlass} />}
placeholder="Search users..."
/>
<div className="flex gap-2">
<Input
value={searchUserFilter}
onChange={(e) => setSearchUserFilter(e.target.value)}
leftIcon={<FontAwesomeIcon icon={faMagnifyingGlass} />}
placeholder="Search users..."
className="flex-1"
/>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<IconButton
ariaLabel="Filter Users"
variant="plain"
size="sm"
className={twMerge(
"flex h-10 w-11 items-center justify-center overflow-hidden border border-mineshaft-600 bg-mineshaft-800 p-0 transition-all hover:border-primary/60 hover:bg-primary/10",
isTableFiltered && "border-primary/50 text-primary"
)}
>
<FontAwesomeIcon icon={faFilter} />
</IconButton>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="w-56">
<DropdownMenuLabel>Filter Users</DropdownMenuLabel>
<DropdownMenuItem
onClick={(e) => {
e.preventDefault();
setAdminsOnly(!adminsOnly);
}}
icon={adminsOnly && <FontAwesomeIcon className="text-primary" icon={faCheckCircle} />}
iconPos="right"
>
<div className="flex w-full items-center justify-between">
<span>Admins Only</span>
<Switch
id="admins-only"
isChecked={adminsOnly}
onCheckedChange={(checked) => setAdminsOnly(checked)}
className="data-[state=checked]:bg-primary-400"
/>
</div>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>
<div className="mt-4">
<TableContainer>
<Table>