Skip to content

Commit

Permalink
Add peer multiselect, optimize dropdown performance for peer selectio…
Browse files Browse the repository at this point in the history
…n, remove 'all' group from some dropdowns, various ui / ux optimizations
  • Loading branch information
heisbrot committed Aug 13, 2024
1 parent c15ef98 commit d272651
Show file tree
Hide file tree
Showing 38 changed files with 1,833 additions and 626 deletions.
Binary file added src/assets/os-icons/FreeBSD.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 9 additions & 1 deletion src/auth/SecureProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,17 @@ export const SecureProvider = ({ children }: Props) => {
const currentPath = usePathname();

useEffect(() => {
let timeout: NodeJS.Timeout | undefined = undefined;
if (!isAuthenticated) {
login(currentPath);
timeout = setTimeout(async () => {
if (!isAuthenticated) {
await login(currentPath);
}
}, 1500);
}
return () => {
clearTimeout(timeout);
};
}, [currentPath, isAuthenticated, login]);

return (
Expand Down
11 changes: 11 additions & 0 deletions src/components/DropdownInfoText.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import * as React from "react";

type Props = {
children: React.ReactNode;
};

export const DropdownInfoText = ({ children }: Props) => {
return (
<div className={"text-center pt-2 mb-6 text-nb-gray-400"}>{children}</div>
);
};
48 changes: 48 additions & 0 deletions src/components/DropdownInput.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { IconArrowBack } from "@tabler/icons-react";
import { cn } from "@utils/helpers";
import { SearchIcon } from "lucide-react";
import * as React from "react";
import { forwardRef } from "react";

type Props = {
value: string;
onChange: (value: string) => void;
placeholder?: string;
};

export const DropdownInput = forwardRef<HTMLInputElement, Props>(
({ value, onChange, placeholder = "Search..." }, ref) => {
return (
<div className={"relative w-full"}>
<input
ref={ref}
className={cn(
"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-nb-gray-400 font-light placeholder:text-neutral-500 pl-10",
)}
value={value}
onChange={(e) => onChange(e.target.value)}
placeholder={placeholder}
/>
<div className={"absolute left-0 top-0 h-full flex items-center pl-4"}>
<div className={"flex items-center"}>
<SearchIcon size={14} />
</div>
</div>
<div className={"absolute right-0 top-0 h-full flex items-center pr-4"}>
<div
className={
"flex items-center bg-nb-gray-800 py-1 px-1.5 rounded-[4px] border border-nb-gray-500"
}
>
<IconArrowBack size={10} />
</div>
</div>
</div>
);
},
);

DropdownInput.displayName = "DropdownInput";
17 changes: 13 additions & 4 deletions src/components/NetworkRouteSelector.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { CommandItem } from "@components/Command";
import FullTooltip from "@components/FullTooltip";
import { Popover, PopoverContent, PopoverTrigger } from "@components/Popover";
import TextWithTooltip from "@components/ui/TextWithTooltip";
import { IconArrowBack } from "@tabler/icons-react";
import useFetchApi from "@utils/api";
import { cn } from "@utils/helpers";
Expand Down Expand Up @@ -108,12 +109,12 @@ export function NetworkRouteSelector({
{value ? (
<div
className={
"flex items-center justify-between text-sm text-white w-full pr-4 pl-1"
"flex items-center justify-between text-sm text-white w-full pr-4 pl-1 gap-2"
}
>
<div className={"flex items-center gap-2.5 text-sm"}>
<NetworkRoutesIcon size={16} />
{value.network_id}
<TextWithTooltip text={value.network_id} maxChars={15} />
</div>

<div
Expand Down Expand Up @@ -224,10 +225,14 @@ export function NetworkRouteSelector({
togglePeer(option);
setOpen(false);
}}
className={"gap-2"}
>
<div className={"flex items-center gap-2.5 text-sm"}>
<NetworkRoutesIcon size={14} />
{option.network_id}
<TextWithTooltip
text={option.network_id}
maxChars={15}
/>
</div>

<div
Expand Down Expand Up @@ -259,7 +264,11 @@ function DomainList({ domains }: { domains?: string[] }) {
<FullTooltip
content={<div className={"text-xs max-w-sm"}>{domains.join(", ")}</div>}
>
<div className={"text-xs text-nb-gray-300"}>
<div
className={
"text-xs text-nb-gray-300 block min-w-0 truncate max-w-[180px]"
}
>
{firstDomain} {domains.length > 1 && "+" + (domains.length - 1)}
</div>
</FullTooltip>
Expand Down
30 changes: 20 additions & 10 deletions src/components/PeerGroupSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ interface MultiSelectProps {
max?: number;
disabled?: boolean;
popoverWidth?: "auto" | number;
hideAllGroup?: boolean;
}
export function PeerGroupSelector({
onChange,
Expand All @@ -37,6 +38,7 @@ export function PeerGroupSelector({
max,
disabled = false,
popoverWidth = "auto",
hideAllGroup = false,
}: MultiSelectProps) {
const { groups, dropdownOptions, setDropdownOptions } = useGroups();
const searchRef = React.useRef<HTMLInputElement>(null);
Expand All @@ -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]);

Expand All @@ -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) => [
Expand Down Expand Up @@ -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 <FolderGit2 size={12} />;
return <FolderGit2 size={12} className={"shrink-0"} />;
}, []);

const peerIcon = useMemo(() => {
return <MonitorSmartphoneIcon size={14} />;
return <MonitorSmartphoneIcon size={14} className={"shrink-0"} />;
}, []);

const [slice, setSlice] = useState(10);
Expand Down Expand Up @@ -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}
Expand Down Expand Up @@ -238,9 +250,7 @@ export function PeerGroupSelector({

<CommandGroup>
<ScrollArea
className={
"max-h-[195px] overflow-y-auto flex flex-col gap-1 pl-2 py-2 pr-3"
}
className={"max-h-[195px] flex flex-col gap-1 pl-2 py-2 pr-3"}
>
{searchedGroupNotFound && (
<CommandItem
Expand Down
Loading

0 comments on commit d272651

Please sign in to comment.