From dab8f0b2610f4d4cacf4691d62c40a7bd3eac676 Mon Sep 17 00:00:00 2001 From: Scott Wilson Date: Thu, 28 Nov 2024 14:29:41 -0800 Subject: [PATCH] improvement: secret tags table pagination --- .../UserProjectsSection/UserGroupsTable.tsx | 5 +- .../SecretTagsSection/SecretTagsSection.tsx | 3 +- .../SecretTagsSection/SecretTagsTable.tsx | 175 +++++++++++++----- 3 files changed, 130 insertions(+), 53 deletions(-) diff --git a/frontend/src/views/Org/UserPage/components/UserProjectsSection/UserGroupsTable.tsx b/frontend/src/views/Org/UserPage/components/UserProjectsSection/UserGroupsTable.tsx index 999ffe794..af136d7ff 100644 --- a/frontend/src/views/Org/UserPage/components/UserProjectsSection/UserGroupsTable.tsx +++ b/frontend/src/views/Org/UserPage/components/UserProjectsSection/UserGroupsTable.tsx @@ -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 (
setSearch(e.target.value)} leftIcon={} - placeholder="Search projects..." + placeholder="Search groups..." /> diff --git a/frontend/src/views/Settings/ProjectSettingsPage/components/SecretTagsSection/SecretTagsSection.tsx b/frontend/src/views/Settings/ProjectSettingsPage/components/SecretTagsSection/SecretTagsSection.tsx index d1ba06835..26be8eb17 100644 --- a/frontend/src/views/Settings/ProjectSettingsPage/components/SecretTagsSection/SecretTagsSection.tsx +++ b/frontend/src/views/Settings/ProjectSettingsPage/components/SecretTagsSection/SecretTagsSection.tsx @@ -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 )} diff --git a/frontend/src/views/Settings/ProjectSettingsPage/components/SecretTagsSection/SecretTagsTable.tsx b/frontend/src/views/Settings/ProjectSettingsPage/components/SecretTagsSection/SecretTagsTable.tsx index cc68b0700..b6793ea1d 100644 --- a/frontend/src/views/Settings/ProjectSettingsPage/components/SecretTagsSection/SecretTagsTable.tsx +++ b/frontend/src/views/Settings/ProjectSettingsPage/components/SecretTagsSection/SecretTagsTable.tsx @@ -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 ( - -
- - - - - - - {isLoading && } - {!isLoading && - data && - data.map(({ id, slug }) => ( - - - - - ))} - {!isLoading && data && data?.length === 0 && ( +
+ setSearch(e.target.value)} + leftIcon={} + placeholder="Search tags..." + /> + +
Slug -
{slug} - - {(isAllowed) => ( - - handlePopUpOpen("deleteTagConfirmation", { - name: slug, - id - }) - } - colorSchema="danger" - ariaLabel="update" - isDisabled={!isAllowed} - > - - - )} - -
+ - + + - )} - -
- - +
+ Slug + + + +
+
-
+ + + {isLoading && } + {!isLoading && + filteredTags.slice(offset, perPage * page).map(({ id, slug }) => ( + + {slug} + + + {(isAllowed) => ( + + handlePopUpOpen("deleteTagConfirmation", { + name: slug, + id + }) + } + size="xs" + colorSchema="danger" + ariaLabel="update" + variant="plain" + isDisabled={!isAllowed} + > + + + )} + + + + ))} + + + {Boolean(filteredTags.length) && ( + + )} + {!isLoading && !filteredTags?.length && ( + + )} + +
); };