feat: improvement org member list (#13859)

* fix: sticky action bar and align checkbox

* feat: make teams filterable and clickable, total members

* fix: update members count

---------

Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
This commit is contained in:
Amit Sharma
2024-03-05 11:09:14 +00:00
committed by GitHub
co-authored by sean-brydon Udit Takkar
parent e39bf37f91
commit 01ac2e640a
3 changed files with 23 additions and 12 deletions
@@ -110,6 +110,7 @@ function reducer(state: State, action: Action): State {
export function UserListTable() {
const { data: session } = useSession();
const { data: currentMembership } = trpc.viewer.organizations.listCurrent.useQuery();
const { data: teams } = trpc.viewer.organizations.getTeams.useQuery();
const tableContainerRef = useRef<HTMLDivElement>(null);
const [state, dispatch] = useReducer(reducer, initialState);
const { t } = useLocale();
@@ -126,6 +127,7 @@ export function UserListTable() {
}
);
const totalDBRowCount = data?.pages?.[0]?.meta?.totalRowCount ?? 0;
const adminOrOwner = currentMembership?.user.role === "ADMIN" || currentMembership?.user.role === "OWNER";
const domain = orgBranding?.fullDomain ?? WEBAPP_URL;
@@ -160,7 +162,7 @@ export function UserListTable() {
{
id: "member",
accessorFn: (data) => data.email,
header: "Member",
header: `Member (${totalDBRowCount})`,
cell: ({ row }) => {
const { username, email } = row.original;
return (
@@ -210,8 +212,9 @@ export function UserListTable() {
},
{
id: "teams",
accessorFn: (data) => data.teams.map((team) => team.name),
header: "Teams",
cell: ({ row }) => {
cell: ({ row, table }) => {
const { teams, accepted, email, username } = row.original;
// TODO: Implement click to filter
return (
@@ -226,13 +229,22 @@ export function UserListTable() {
</Badge>
)}
{teams.map((team) => (
<Badge key={team.id} variant="gray">
<Badge
key={team.id}
variant="gray"
onClick={() => {
table.getColumn("teams")?.setFilterValue([team.name]);
}}>
{team.name}
</Badge>
))}
</div>
);
},
filterFn: (rows, _, filterValue: string[]) => {
const teamNames = rows.original.teams.map((team) => team.name);
return filterValue.some((value: string) => teamNames.includes(value));
},
},
{
id: "actions",
@@ -262,11 +274,10 @@ export function UserListTable() {
];
return cols;
}, [session?.user.id, adminOrOwner, dispatch, domain]);
}, [session?.user.id, adminOrOwner, dispatch, domain, totalDBRowCount]);
//we must flatten the array of arrays from the useInfiniteQuery hook
const flatData = useMemo(() => data?.pages?.flatMap((page) => page.rows) ?? [], [data]) as User[];
const totalDBRowCount = data?.pages?.[0]?.meta?.totalRowCount ?? 0;
const totalFetched = flatData.length;
//called on scroll and possibly on mount to fetch more data as the user scrolls and reaches bottom of table
@@ -342,6 +353,11 @@ export function UserListTable() {
{ label: "Member", value: "MEMBER" },
],
},
{
tableAccessor: "teams",
title: "Teams",
options: teams ? teams.map((team) => ({ label: team.name, value: team.name })) : [],
},
]}
/>
@@ -1,4 +1,3 @@
import { isOrganisationAdmin } from "@calcom/lib/server/queries/organisations";
import { prisma } from "@calcom/prisma";
import { TRPCError } from "@trpc/server";
@@ -16,10 +15,6 @@ export async function getTeamsHandler({ ctx }: GetTeamsHandler) {
if (!currentUser.organizationId) throw new TRPCError({ code: "UNAUTHORIZED" });
// check if user is admin of organization
if (!(await isOrganisationAdmin(currentUser?.id, currentUser.organizationId)))
throw new TRPCError({ code: "UNAUTHORIZED" });
const allOrgTeams = await prisma.team.findMany({
where: {
parentId: currentUser.organizationId,
+2 -2
View File
@@ -19,7 +19,7 @@ const TableHeader = React.forwardRef<HTMLTableSectionElement, React.HTMLAttribut
({ className, ...props }, ref) => (
<thead
ref={ref}
className={classNames("[&_tr]:bg-subtle md:sticky md:top-[4.25rem] md:z-10 [&_tr]:border-b", className)}
className={classNames("[&_tr]:bg-subtle md:z-10 [&_tr]:border-b", className)}
{...props}
/>
)
@@ -59,7 +59,7 @@ const TableHead = React.forwardRef<HTMLTableCellElement, React.ThHTMLAttributes<
<th
ref={ref}
className={classNames(
"text-default h-12 px-4 text-left align-middle font-medium [&:has([role=checkbox])]:pr-0",
"text-default h-12 px-2 text-left align-middle font-medium [&:has([role=checkbox])]:pr-0",
className
)}
{...props}