mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-09 11:28:18 +00:00
improvement: add search to cloud integrations
This commit is contained in:
+47
-9
@@ -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>
|
||||||
)}
|
)}
|
||||||
<h1 className="text-3xl font-semibold">{t("integrations.cloud-integrations")}</h1>
|
<div className="flex w-full flex-col justify-between gap-4 whitespace-nowrap lg:flex-row lg:items-end lg:gap-8">
|
||||||
<p className="text-base text-gray-400">{t("integrations.click-to-start")}</p>
|
<div className="flex-1">
|
||||||
|
<h1 className="text-3xl font-semibold">{t("integrations.cloud-integrations")}</h1>
|
||||||
|
<p className="text-base text-gray-400">{t("integrations.click-to-start")}</p>
|
||||||
|
</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>
|
||||||
<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">
|
||||||
|
|||||||
Reference in New Issue
Block a user