+
{firstDomain} {domains.length > 1 && "+" + (domains.length - 1)}
diff --git a/src/components/PeerGroupSelector.tsx b/src/components/PeerGroupSelector.tsx
index c75994dc..c43402b2 100644
--- a/src/components/PeerGroupSelector.tsx
+++ b/src/components/PeerGroupSelector.tsx
@@ -29,6 +29,7 @@ interface MultiSelectProps {
max?: number;
disabled?: boolean;
popoverWidth?: "auto" | number;
+ hideAllGroup?: boolean;
}
export function PeerGroupSelector({
onChange,
@@ -37,6 +38,7 @@ export function PeerGroupSelector({
max,
disabled = false,
popoverWidth = "auto",
+ hideAllGroup = false,
}: MultiSelectProps) {
const { groups, dropdownOptions, setDropdownOptions } = useGroups();
const searchRef = React.useRef
(null);
@@ -47,7 +49,13 @@ export function PeerGroupSelector({
useEffect(() => {
if (!groups) return;
const sortedGroups = sortBy([...groups], "name") as Group[];
- setDropdownOptions(unionBy(sortedGroups, dropdownOptions, "name"));
+
+ let uniqueGroups = unionBy(sortedGroups, dropdownOptions, "name");
+ uniqueGroups = hideAllGroup
+ ? uniqueGroups.filter((group) => group.name !== "All")
+ : uniqueGroups;
+
+ setDropdownOptions(uniqueGroups);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [groups]);
@@ -66,8 +74,11 @@ export function PeerGroupSelector({
const option = dropdownOptions.find((option) => option.name == name);
const groupPeers: GroupPeer[] | undefined =
(group?.peers as GroupPeer[]) || [];
- groupPeers &&
- groupPeers.push({ id: peer?.id as string, name: peer?.name as string });
+
+ if (peer) {
+ groupPeers &&
+ groupPeers.push({ id: peer?.id as string, name: peer?.name as string });
+ }
if (!group && !option) {
setDropdownOptions((previous) => [
@@ -100,17 +111,18 @@ export function PeerGroupSelector({
const isSearching = search.length > 0;
const groupDoesNotExist =
dropdownOptions.filter((item) => item.name == trim(search)).length == 0;
- return isSearching && groupDoesNotExist;
+ const isAllGroup = search.toLowerCase() == "all";
+ return isSearching && groupDoesNotExist && !isAllGroup;
}, [search, dropdownOptions]);
const [open, setOpen] = useState(false);
const folderIcon = useMemo(() => {
- return ;
+ return ;
}, []);
const peerIcon = useMemo(() => {
- return ;
+ return ;
}, []);
const [slice, setSlice] = useState(10);
@@ -203,7 +215,7 @@ export function PeerGroupSelector({
"min-h-[42px] w-full relative",
"border-b-0 border-t-0 border-r-0 border-l-0 border-neutral-200 dark:border-nb-gray-700 items-center",
"bg-transparent text-sm outline-none focus-visible:outline-none ring-0 focus-visible:ring-0",
- "dark:placeholder:text-neutral-500 font-light placeholder:text-neutral-500 pl-10",
+ "dark:placeholder:text-nb-gray-400 font-light placeholder:text-neutral-500 pl-10",
)}
ref={searchRef}
value={search}
@@ -238,9 +250,7 @@ export function PeerGroupSelector({
{searchedGroupNotFound && (
);
+MapPinIcon.displayName = "MapPinIcon";
+
+const LinuxIcon = memo(() => (
+
+
+
+));
+LinuxIcon.displayName = "LinuxIcon";
+
interface MultiSelectProps {
value?: Peer;
onChange: React.Dispatch>;
@@ -23,6 +33,13 @@ interface MultiSelectProps {
disabled?: boolean;
}
+const searchPredicate = (item: Peer, query: string) => {
+ const lowerCaseQuery = query.toLowerCase();
+ if (item.name.toLowerCase().includes(lowerCaseQuery)) return true;
+ if (item.hostname.toLowerCase().includes(lowerCaseQuery)) return true;
+ return item.ip.toLowerCase().startsWith(lowerCaseQuery);
+};
+
export function PeerSelector({
onChange,
value,
@@ -30,13 +47,16 @@ export function PeerSelector({
disabled = false,
}: MultiSelectProps) {
const { data: peers } = useFetchApi("/peers");
-
- const [dropdownOptions, setDropdownOptions] = useState([]);
- const searchRef = React.useRef(null);
const [inputRef, { width }] = useElementSize();
- const [search, setSearch] = useState("");
- // Update dropdown options when peers change
+ const [unfilteredItems, setUnfilteredItems] = useState([]);
+ const [filteredItems, search, setSearch] = useSearch(
+ unfilteredItems,
+ searchPredicate,
+ { filter: true, debounce: 150 },
+ );
+
+ // Update unfiltered items when peers change
useEffect(() => {
if (!peers) return;
@@ -56,7 +76,7 @@ export function PeerSelector({
});
}
- setDropdownOptions(unionBy(options, dropdownOptions, "id"));
+ setUnfilteredItems(unionBy(options, unfilteredItems, "id"));
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [peers]);
@@ -68,44 +88,11 @@ export function PeerSelector({
onChange(peer);
setSearch("");
}
+ setOpen(false);
};
- const peerNotFound = useMemo(() => {
- const isSearching = search.length > 0;
-
- // Search peer by ip or name
- const peerFound =
- dropdownOptions.filter((item) => {
- return (
- item.name.includes(search) ||
- item.hostname.includes(search) ||
- item.ip.includes(search)
- );
- }).length > 0;
-
- return isSearching && !peerFound;
- }, [search, dropdownOptions]);
-
const [open, setOpen] = useState(false);
- const [slice, setSlice] = useState(10);
-
- useEffect(() => {
- if (open) {
- setTimeout(() => {
- setSlice(dropdownOptions.length);
- }, 100);
- } else {
- setSlice(10);
- }
- }, [open, dropdownOptions]);
-
- const LinuxIcon = (
-
-
-
- );
-
return (
- {LinuxIcon}
+
@@ -150,7 +137,7 @@ export function PeerSelector({
"text-neutral-500 dark:text-nb-gray-300 font-medium flex items-center gap-1 font-mono text-[10px]"
}
>
-
+
{value.ip}