diff --git a/components/filters/CustomSearchInput.tsx b/components/filters/CustomSearchInput.tsx index b3a827abb7..98310f10b5 100644 --- a/components/filters/CustomSearchInput.tsx +++ b/components/filters/CustomSearchInput.tsx @@ -1,17 +1,14 @@ import { Input } from "@nextui-org/react"; +import debounce from "lodash.debounce"; import { XCircle } from "lucide-react"; import { useRouter, useSearchParams } from "next/navigation"; import React, { useCallback, useEffect, useState } from "react"; -import { useDebounce } from "../../hooks/useDebounce"; - export const CustomSearchInput: React.FC = () => { const router = useRouter(); const searchParams = useSearchParams(); - const [searchQuery, setSearchQuery] = useState(() => { - return searchParams.get("filter[search]") || ""; - }); - const debouncedSearchQuery = useDebounce(searchQuery, 300); + + const [searchQuery, setSearchQuery] = useState(""); const applySearch = useCallback( (query: string) => { @@ -21,19 +18,22 @@ export const CustomSearchInput: React.FC = () => { } else { params.delete("filter[search]"); } - router.replace(`?${params.toString()}`, { scroll: false }); + router.push(`?${params.toString()}`, { scroll: false }); }, [router, searchParams], ); + const debouncedChangeHandler = useCallback(debounce(applySearch, 300), []); + const clearIconSearch = () => { setSearchQuery(""); applySearch(""); }; useEffect(() => { - applySearch(debouncedSearchQuery); - }, [debouncedSearchQuery, applySearch]); + const searchFromUrl = searchParams.get("filter[search]") || ""; + setSearchQuery(searchFromUrl); + }, [searchParams]); return ( { label="Search" labelPlacement="inside" value={searchQuery} - onChange={(e) => setSearchQuery(e.target.value)} - onKeyDown={(e) => { - if (e.key === "Enter") { - applySearch(searchQuery); - } + onChange={(e) => { + const value = e.target.value; + setSearchQuery(value); + debouncedChangeHandler(value); }} endContent={ searchQuery && ( diff --git a/components/icons/Icons.tsx b/components/icons/Icons.tsx index 6024849b2d..f665b49628 100644 --- a/components/icons/Icons.tsx +++ b/components/icons/Icons.tsx @@ -464,6 +464,117 @@ export const NotificationIcon: React.FC = ({ ); +export const IdIcon: React.FC = ({ + size = 24, + width, + height, + ...props +}) => ( + + + +); + +export const DoneIcon: React.FC = ({ + size, + height, + width, + ...props +}) => { + return ( + + + + ); +}; + +export const CopyIcon: React.FC = ({ + size, + height, + width, + ...props +}) => { + return ( + + + + ); +}; + +export const FlowIcon: React.FC = ({ + size, + height, + width, + ...props +}) => { + return ( + + + + ); +}; + +export const ConnectionIcon: React.FC = ({ + size, + height, + width, + ...props +}) => { + return ( + + + + ); +}; + export const SuccessIcon: React.FC = ({ size = 24, width, diff --git a/components/providers/CheckConnectionProvider.tsx b/components/providers/CheckConnectionProvider.tsx index a7d4ec8360..2fadafad04 100644 --- a/components/providers/CheckConnectionProvider.tsx +++ b/components/providers/CheckConnectionProvider.tsx @@ -27,15 +27,16 @@ export const CheckConnectionProvider = ({ id }: { id: string }) => { }); } else { toast({ - title: "Success!", - description: "The connection was updated successfully.", + title: "Checking", + description: "The task was launched successfully", }); } } + return (
- + ); }; diff --git a/components/providers/ProviderInfo.tsx b/components/providers/ProviderInfo.tsx index 8730e6cfcd..96f9df0cbd 100644 --- a/components/providers/ProviderInfo.tsx +++ b/components/providers/ProviderInfo.tsx @@ -1,35 +1,47 @@ import React from "react"; -import { WifiIcon, WifiOffIcon, WifiPendingIcon } from "../icons"; +import { ConnectionIcon } from "../icons"; import { AWSProviderBadge, AzureProviderBadge, GCPProviderBadge, KS8ProviderBadge, } from "../icons/providers-badge"; +import { CustomLoader } from "../ui/custom"; interface ProviderInfoProps { connected: boolean | null; provider: "aws" | "azure" | "gcp" | "kubernetes"; providerAlias: string; - providerId: string; } export const ProviderInfo: React.FC = ({ connected, provider, providerAlias, - providerId, }) => { const getIcon = () => { switch (connected) { case true: - return ; + return ( +
+ +
+ ); case false: - return ; + return ( +
+ +
+ ); case null: + return ( +
+ +
+ ); default: - return ; + return ; } }; @@ -49,13 +61,15 @@ export const ProviderInfo: React.FC = ({ }; return ( -
-
-
{getIcon()}
-
{getProviderLogo()}
-
- {providerAlias} - {providerId} +
+
+
+
{getProviderLogo()}
+
{getIcon()}
+
+ {providerAlias} + {/* */} +
diff --git a/components/providers/SnippetIdProvider.tsx b/components/providers/SnippetIdProvider.tsx new file mode 100644 index 0000000000..775e72eaf7 --- /dev/null +++ b/components/providers/SnippetIdProvider.tsx @@ -0,0 +1,28 @@ +import { Snippet } from "@nextui-org/react"; +import React from "react"; + +import { CopyIcon, DoneIcon, IdIcon } from "../icons"; + +interface SnippetIdProviderProps { + providerId: string; +} +export const SnippetIdProvider: React.FC = ({ + providerId, +}) => { + return ( + } + checkIcon={} + > +

+ + {providerId} +

+
+ ); +}; diff --git a/components/providers/index.ts b/components/providers/index.ts index 58c8dae90f..a0129d3520 100644 --- a/components/providers/index.ts +++ b/components/providers/index.ts @@ -7,6 +7,7 @@ export * from "./DateWithTime"; export * from "./DeleteProvider"; export * from "./ProviderInfo"; export * from "./ScanStatus"; +export * from "./SnippetIdProvider"; export * from "./table/ColumnsProvider"; export * from "./table/DataTableColumnHeader"; export * from "./table/DataTablePagination"; diff --git a/components/providers/table/ColumnsProvider.tsx b/components/providers/table/ColumnsProvider.tsx index e08050e620..33c79a25bd 100644 --- a/components/providers/table/ColumnsProvider.tsx +++ b/components/providers/table/ColumnsProvider.tsx @@ -31,12 +31,14 @@ import { EditDocumentBulkIcon, } from "@nextui-org/shared-icons"; +import { SnippetIdProvider } from "../SnippetIdProvider"; + const iconClasses = "text-2xl text-default-500 pointer-events-none flex-shrink-0"; export const ColumnsProvider: ColumnDef[] = [ { - header: "ID", + header: "n", cell: ({ row }) =>

{row.index + 1}

, }, { @@ -46,18 +48,29 @@ export const ColumnsProvider: ColumnDef[] = [ ), cell: ({ row }) => { const { - attributes: { connection, provider, alias, provider_id }, + attributes: { connection, provider, alias }, } = getProviderData(row); return ( ); }, }, + { + accessorKey: "id", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const { + attributes: { provider_id }, + } = getProviderData(row); + return ; + }, + }, { accessorKey: "status", header: "Scan Status", @@ -144,6 +157,7 @@ export const ColumnsProvider: ColumnDef[] = [ key="new" description="Check the connection to the provider" shortcut="⌘N" + textValue="Check Connection" startContent={} > @@ -152,6 +166,7 @@ export const ColumnsProvider: ColumnDef[] = [ key="edit" description="Allows you to edit the provider" shortcut="⌘⇧E" + textValue="Edit Provider" startContent={ } diff --git a/components/ui/custom/CustomLoader.tsx b/components/ui/custom/CustomLoader.tsx new file mode 100644 index 0000000000..4dd67b6e78 --- /dev/null +++ b/components/ui/custom/CustomLoader.tsx @@ -0,0 +1,16 @@ +"use client"; + +import { useEffect, useState } from "react"; + +export const CustomLoader = (props: { size?: "small" }) => { + const [loadingSpinner, setloadingSpinner] = useState(0); + const loadingChars = "|/-\\"; + + const textClasses = `w-xs px-xs ${props.size === "small" ? "!text-s" : ""}`; + + useEffect(() => { + setTimeout(() => setloadingSpinner(loadingSpinner + 1), 150); + }, [loadingSpinner]); + + return

{loadingChars[loadingSpinner % 4]}

; +}; diff --git a/components/ui/custom/index.ts b/components/ui/custom/index.ts index dbc111a3cc..1599c7850f 100644 --- a/components/ui/custom/index.ts +++ b/components/ui/custom/index.ts @@ -1,3 +1,4 @@ export * from "./CustomBox"; export * from "./CustomButtonClientAction"; export * from "./CustomInput"; +export * from "./CustomLoader"; diff --git a/hooks/index.ts b/hooks/index.ts index b32251b922..709aadd864 100644 --- a/hooks/index.ts +++ b/hooks/index.ts @@ -1,2 +1 @@ -export * from "./useDebounce"; export * from "./useLocalStorage"; diff --git a/hooks/useDebounce.ts b/hooks/useDebounce.ts deleted file mode 100644 index f0d8d7c3bf..0000000000 --- a/hooks/useDebounce.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { useEffect, useState } from "react"; - -export function useDebounce(value: T, delay?: number): T { - const [debouncedValue, setDebouncedValue] = useState(value); - - useEffect(() => { - const timer = setTimeout(() => setDebouncedValue(value), delay ?? 900); - - return () => { - clearTimeout(timer); - }; - }, [value, delay]); - - return debouncedValue; -}