Skip to content

Commit

Permalink
[WIP] serial number lookup + filter to only "All" group
Browse files Browse the repository at this point in the history
Signed-off-by: Edouard Vanbelle <[email protected]>
  • Loading branch information
EdouardVanbelle committed Dec 23, 2024
1 parent 2aa7b0c commit 960200f
Show file tree
Hide file tree
Showing 4 changed files with 235 additions and 101 deletions.
2 changes: 1 addition & 1 deletion src/modules/groups/AssignPeerToGroupModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,6 @@ const PeersTableColumns: ColumnDef<Peer>[] = [
header: ({ column }) => {
return <DataTableHeader column={column}>OS</DataTableHeader>;
},
cell: ({ row }) => <PeerOSCell os={row.original.os} />,
cell: ({ row }) => <PeerOSCell os={row.original.os} serial={row.original.serial_number} />,
},
];
79 changes: 69 additions & 10 deletions src/modules/groups/GroupSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,23 @@ import { Group } from "@/interfaces/Group";

interface MultiSelectProps {
values: string[];
onChange: (items: string[]) => void;
exactValue?: string;
onChange: (items: string[], exactItem?: string) => void;
disabled?: boolean;
popoverWidth?: "auto" | number;
groups: Group[] | undefined;
unassignedCount?: number;
defaultGroupName?: string;
}
export function GroupSelector({
onChange,
values,
exactValue: exactValues,
disabled = false,
popoverWidth = 400,
groups,
unassignedCount,
defaultGroupName = "All", //defined as a property, no clue if this value may change in the future
}: MultiSelectProps) {
const searchRef = React.useRef<HTMLInputElement>(null);
const [inputRef, { width }] = useElementSize<HTMLButtonElement>();
Expand All @@ -40,9 +46,20 @@ export function GroupSelector({
const toggle = (code: string) => {
const isSelected = values.find((c) => c == code) != undefined;
if (isSelected) {
onChange && onChange(values.filter((c) => c != code));
onChange && onChange(values.filter((c) => c != code), undefined);
} else {
onChange && onChange([...values, code]);
onChange && onChange([...values, code], undefined);
setSearch("");
}
};

const toggleExactGroup = (code: string) => {
const isSelected = exactValues == code;
if (isSelected) {
onChange && onChange([], undefined);
setSearch("");
} else {
onChange && onChange([], code);
setSearch("");
}
};
Expand All @@ -65,11 +82,13 @@ export function GroupSelector({
<Button variant={"secondary"} disabled={disabled} ref={inputRef}>
<FolderGit2 size={16} className={"shrink-0"} />
<div className={"w-full flex justify-between"}>
{values.length > 0 ? (
<div>{values.length} Group(s)</div>
) : (
"All Groups"
)}
{
exactValues != undefined
? ("Unassigned peers")
: values.length > 0
? (`${values.length} Group(s)`)
: ("All Groups")
}
<div className={"pl-2"}>
<ChevronsUpDown size={18} className={"shrink-0"} />
</div>
Expand Down Expand Up @@ -132,7 +151,6 @@ export function GroupSelector({
</div>
</div>
</div>

<ScrollArea
className={
"max-h-[380px] overflow-y-auto flex flex-col gap-1 pl-2 py-2 pr-3"
Expand All @@ -141,7 +159,48 @@ export function GroupSelector({
<CommandGroup>
<div className={""}>
<div className={"grid grid-cols-1 gap-1"}>
{orderBy(groups, "name")?.map((item) => {
<CommandItem
className={"p-1"}
onSelect={() => {
toggleExactGroup( defaultGroupName);
searchRef.current?.focus();
}}
onClick={(e) => e.preventDefault()}
>
<div
className={
"text-neutral-500 dark:text-nb-gray-300 font-medium flex items-center gap-3 py-1 px-1 w-full"
}
>
<Checkbox checked={exactValues == defaultGroupName}/>
<div
className={
"flex justify-between items-center w-full"
}
>
<div
className={
"flex items-center gap-2 whitespace-nowrap text-sm"
}
>
<FolderGit2 size={13} className={"shrink-0"} />
<TextWithTooltip text={"Unassigned peers"} />
</div>
<div
className={
"flex items-center gap-2 text-xs text-nb-gray-200/60"
}
>
<MonitorSmartphoneIcon size={13} />
{unassignedCount} Peer(s)
</div>
</div>
</div>
</CommandItem>
<hr />
{orderBy(groups, "name")
?.filter((group) => group.name != defaultGroupName) // Ignore default group
?.map((item) => {
const value = item?.name || "";
if (value === "") return null;
const isSelected =
Expand Down
42 changes: 40 additions & 2 deletions src/modules/peers/PeerOSCell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
TooltipProvider,
TooltipTrigger,
} from "@components/Tooltip";
import { Barcode, Laptop } from "lucide-react";
import Image from "next/image";
import React, { useMemo } from "react";
import { FaWindows } from "react-icons/fa6";
Expand All @@ -14,7 +15,7 @@ import FreeBSDLogo from "@/assets/os-icons/FreeBSD.png";
import { getOperatingSystem } from "@/hooks/useOperatingSystem";
import { OperatingSystem } from "@/interfaces/OperatingSystem";

export function PeerOSCell({ os }: { os: string }) {
export function PeerOSCell({ os, serial }: { os: string, serial?: string }) {
return (
<TooltipProvider>
<Tooltip delayDuration={1}>
Expand All @@ -34,13 +35,50 @@ export function PeerOSCell({ os }: { os: string }) {
</div>
</TooltipTrigger>
<TooltipContent>
<div className={"text-neutral-300 flex flex-col gap-1"}>{os}</div>
<ListItem
icon={<Laptop size={14} />}
label={"OS"}
value={os}
/>
{ (serial !== undefined) &&
<ListItem

icon={<Barcode size={14} />}
label={"Serial"}
value={serial}
/>
}
</TooltipContent>
</Tooltip>
</TooltipProvider>
);
}

const ListItem = ({
icon,
label,
value,
}: {
icon: React.ReactNode;
label: string;
value: string | React.ReactNode;
}) => {
return (
<div
className={
"flex justify-between gap-5 border-b border-nb-gray-920 py-2 px-4 last:border-b-0 text-xs"
}
>
<div className={"flex items-center gap-2 text-nb-gray-100 font-medium"}>
{icon}
{label}
</div>
<div className={"text-nb-gray-400"}>{value}</div>
</div>
);
};


export function OSLogo({ os }: { os: string }) {
const icon = useMemo(() => {
return getOperatingSystem(os);
Expand Down
Loading

0 comments on commit 960200f

Please sign in to comment.