improvement: secret tags table pagination

This commit is contained in:
Scott Wilson
2024-11-28 14:29:41 -08:00
parent 4293665130
commit dab8f0b261
3 changed files with 130 additions and 53 deletions

View File

@ -57,7 +57,7 @@ export const UserGroupsTable = ({ handlePopUpOpen, orgMembership }: Props) => {
const filteredGroupMemberships = useMemo(
() =>
groupMemberships
?.filter((group) => group.name.toLowerCase().includes(search.trim().toLowerCase()))
.filter((group) => group.name.toLowerCase().includes(search.trim().toLowerCase()))
.sort((a, b) => {
const [membershipOne, membershipTwo] =
orderDirection === OrderByDirection.ASC ? [a, b] : [b, a];
@ -72,13 +72,14 @@ export const UserGroupsTable = ({ handlePopUpOpen, orgMembership }: Props) => {
offset,
setPage
});
return (
<div>
<Input
value={search}
onChange={(e) => setSearch(e.target.value)}
leftIcon={<FontAwesomeIcon icon={faMagnifyingGlass} />}
placeholder="Search projects..."
placeholder="Search groups..."
/>
<TableContainer className="mt-4">
<Table>

View File

@ -19,7 +19,6 @@ import { SecretTagsTable } from "./SecretTagsTable";
type DeleteModalData = { name: string; id: string };
export const SecretTagsSection = (): JSX.Element => {
const { popUp, handlePopUpToggle, handlePopUpClose, handlePopUpOpen } = usePopUp([
"CreateSecretTag",
"deleteTagConfirmation"
@ -65,7 +64,7 @@ export const SecretTagsSection = (): JSX.Element => {
}}
isDisabled={!isAllowed}
>
Create tag
Create Tag
</Button>
)}
</ProjectPermissionCan>

View File

@ -1,10 +1,20 @@
import { faTags, faTrashCan } from "@fortawesome/free-solid-svg-icons";
import { useMemo } from "react";
import {
faArrowDown,
faArrowUp,
faMagnifyingGlass,
faSearch,
faTag,
faTrashCan
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { ProjectPermissionCan } from "@app/components/permissions";
import {
EmptyState,
IconButton,
Input,
Pagination,
Table,
TableContainer,
TableSkeleton,
@ -15,7 +25,9 @@ import {
Tr
} from "@app/components/v2";
import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@app/context";
import { usePagination, useResetPageHelper } from "@app/hooks";
import { useGetWsTags } from "@app/hooks/api";
import { OrderByDirection } from "@app/hooks/api/generic/types";
import { UsePopUpState } from "@app/hooks/usePopUp";
type Props = {
@ -31,59 +43,124 @@ type Props = {
) => void;
};
enum TagsOrderBy {
Slug = "slug"
}
export const SecretTagsTable = ({ handlePopUpOpen }: Props) => {
const { currentWorkspace } = useWorkspace();
const { data, isLoading } = useGetWsTags(currentWorkspace?.id ?? "");
const { data: tags = [], isLoading } = useGetWsTags(currentWorkspace?.id ?? "");
const {
search,
setSearch,
setPage,
page,
perPage,
setPerPage,
offset,
orderDirection,
toggleOrderDirection
} = usePagination(TagsOrderBy.Slug, { initPerPage: 10 });
const filteredTags = useMemo(
() =>
tags
.filter((tag) => tag.slug.toLowerCase().includes(search.trim().toLowerCase()))
.sort((a, b) => {
const [tagOne, tagTwo] = orderDirection === OrderByDirection.ASC ? [a, b] : [b, a];
return tagOne.slug.toLowerCase().localeCompare(tagTwo.slug.toLowerCase());
}),
[tags, orderDirection, search]
);
useResetPageHelper({
totalCount: filteredTags.length,
offset,
setPage
});
return (
<TableContainer className="mt-4">
<Table>
<THead>
<Tr>
<Th>Slug</Th>
<Th aria-label="button" />
</Tr>
</THead>
<TBody>
{isLoading && <TableSkeleton columns={3} innerKey="secret-tags" />}
{!isLoading &&
data &&
data.map(({ id, slug }) => (
<Tr key={id}>
<Td>{slug}</Td>
<Td className="flex items-center justify-end">
<ProjectPermissionCan
I={ProjectPermissionActions.Delete}
a={ProjectPermissionSub.Tags}
>
{(isAllowed) => (
<IconButton
onClick={() =>
handlePopUpOpen("deleteTagConfirmation", {
name: slug,
id
})
}
colorSchema="danger"
ariaLabel="update"
isDisabled={!isAllowed}
>
<FontAwesomeIcon icon={faTrashCan} />
</IconButton>
)}
</ProjectPermissionCan>
</Td>
</Tr>
))}
{!isLoading && data && data?.length === 0 && (
<div>
<Input
value={search}
onChange={(e) => setSearch(e.target.value)}
leftIcon={<FontAwesomeIcon icon={faMagnifyingGlass} />}
placeholder="Search tags..."
/>
<TableContainer className="mt-4">
<Table>
<THead>
<Tr>
<Td colSpan={3}>
<EmptyState title="No secret tags found" icon={faTags} />
</Td>
<Th className="w-full">
<div className="flex items-center">
Slug
<IconButton
variant="plain"
className="ml-2"
ariaLabel="sort"
onClick={toggleOrderDirection}
>
<FontAwesomeIcon
icon={orderDirection === OrderByDirection.DESC ? faArrowUp : faArrowDown}
/>
</IconButton>
</div>
</Th>
<Th aria-label="button" />
</Tr>
)}
</TBody>
</Table>
</TableContainer>
</THead>
<TBody>
{isLoading && <TableSkeleton columns={3} innerKey="secret-tags" />}
{!isLoading &&
filteredTags.slice(offset, perPage * page).map(({ id, slug }) => (
<Tr key={id}>
<Td>{slug}</Td>
<Td className="flex items-center justify-end">
<ProjectPermissionCan
I={ProjectPermissionActions.Delete}
a={ProjectPermissionSub.Tags}
>
{(isAllowed) => (
<IconButton
onClick={() =>
handlePopUpOpen("deleteTagConfirmation", {
name: slug,
id
})
}
size="xs"
colorSchema="danger"
ariaLabel="update"
variant="plain"
isDisabled={!isAllowed}
>
<FontAwesomeIcon icon={faTrashCan} />
</IconButton>
)}
</ProjectPermissionCan>
</Td>
</Tr>
))}
</TBody>
</Table>
{Boolean(filteredTags.length) && (
<Pagination
count={filteredTags.length}
page={page}
perPage={perPage}
onChangePage={setPage}
onChangePerPage={setPerPage}
/>
)}
{!isLoading && !filteredTags?.length && (
<EmptyState
title={tags.length ? "No tags match search..." : "No tags found for project"}
icon={tags.length ? faSearch : faTag}
/>
)}
</TableContainer>
</div>
);
};