improvement: add search to cloud integrations

This commit is contained in:
Scott Wilson
2024-12-04 21:00:33 -08:00
parent 132de1479d
commit a078cb6059
@@ -1,11 +1,24 @@
import { useMemo } from "react"; import { useMemo, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { faCheck, faChevronLeft, faXmark } from "@fortawesome/free-solid-svg-icons"; import {
faCheck,
faChevronLeft,
faMagnifyingGlass,
faSearch,
faXmark
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { NoEnvironmentsBanner } from "@app/components/integrations/NoEnvironmentsBanner"; import { NoEnvironmentsBanner } from "@app/components/integrations/NoEnvironmentsBanner";
import { createNotification } from "@app/components/notifications"; import { createNotification } from "@app/components/notifications";
import { Button, DeleteActionModal, Skeleton, Tooltip } from "@app/components/v2"; import {
Button,
DeleteActionModal,
EmptyState,
Input,
Skeleton,
Tooltip
} from "@app/components/v2";
import { import {
ProjectPermissionActions, ProjectPermissionActions,
ProjectPermissionSub, ProjectPermissionSub,
@@ -54,6 +67,12 @@ export const CloudIntegrationSection = ({
return sortedIntegrations; return sortedIntegrations;
}, [cloudIntegrations, currentWorkspace?.environments]); }, [cloudIntegrations, currentWorkspace?.environments]);
const [search, setSearch] = useState("");
const filteredIntegrations = sortedCloudIntegrations?.filter((cloudIntegration) =>
cloudIntegration.name.toLowerCase().includes(search.toLowerCase().trim())
);
return ( return (
<div> <div>
<div className="px-5"> <div className="px-5">
@@ -61,7 +80,7 @@ export const CloudIntegrationSection = ({
<NoEnvironmentsBanner projectId={currentWorkspace.id} /> <NoEnvironmentsBanner projectId={currentWorkspace.id} />
)} )}
</div> </div>
<div className="m-4 mt-7 flex max-w-5xl flex-col items-start justify-between px-2 text-xl"> <div className="m-4 mt-7 flex flex-col items-start justify-between px-2 text-xl">
{onViewActiveIntegrations && ( {onViewActiveIntegrations && (
<Button <Button
variant="link" variant="link"
@@ -71,16 +90,28 @@ export const CloudIntegrationSection = ({
Back to Integrations Back to Integrations
</Button> </Button>
)} )}
<div className="flex w-full flex-col justify-between gap-4 whitespace-nowrap lg:flex-row lg:items-end lg:gap-8">
<div className="flex-1">
<h1 className="text-3xl font-semibold">{t("integrations.cloud-integrations")}</h1> <h1 className="text-3xl font-semibold">{t("integrations.cloud-integrations")}</h1>
<p className="text-base text-gray-400">{t("integrations.click-to-start")}</p> <p className="text-base text-gray-400">{t("integrations.click-to-start")}</p>
</div> </div>
<Input
value={search}
onChange={(e) => setSearch(e.target.value)}
leftIcon={<FontAwesomeIcon icon={faMagnifyingGlass} />}
placeholder="Search cloud integrations..."
containerClassName="flex-1 h-min text-base"
/>
</div>
</div>
<div className="mx-6 grid grid-cols-3 gap-4 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 2xl:grid-cols-7"> <div className="mx-6 grid grid-cols-3 gap-4 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 2xl:grid-cols-7">
{isLoading && {isLoading &&
Array.from({ length: 12 }).map((_, index) => ( Array.from({ length: 12 }).map((_, index) => (
<Skeleton className="h-32" key={`cloud-integration-skeleton-${index + 1}`} /> <Skeleton className="h-32" key={`cloud-integration-skeleton-${index + 1}`} />
))} ))}
{!isLoading &&
sortedCloudIntegrations?.map((cloudIntegration) => ( {!isLoading && filteredIntegrations.length ? (
filteredIntegrations.map((cloudIntegration) => (
<div <div
onKeyDown={() => null} onKeyDown={() => null}
role="button" role="button"
@@ -146,7 +177,14 @@ export const CloudIntegrationSection = ({
</div> </div>
)} )}
</div> </div>
))} ))
) : (
<EmptyState
className="col-span-full h-32 w-full rounded-md bg-transparent pt-14"
title="No cloud integrations match search..."
icon={faSearch}
/>
)}
</div> </div>
{isEmpty && ( {isEmpty && (
<div className="mx-6 grid max-w-5xl grid-cols-4 grid-rows-2 gap-4"> <div className="mx-6 grid max-w-5xl grid-cols-4 grid-rows-2 gap-4">