diff --git a/src/components/table/DataTableToolTipButton.tsx b/src/components/table/DataTableToolTipButton.tsx
new file mode 100644
index 00000000..c6acebbf
--- /dev/null
+++ b/src/components/table/DataTableToolTipButton.tsx
@@ -0,0 +1,48 @@
+import Button from "@components/Button";
+import { Tooltip, TooltipContent, TooltipTrigger } from "@components/Tooltip";
+import { motion } from "framer-motion";
+import { RefreshCcw } from "lucide-react";
+import * as React from "react";
+import { useState } from "react";
+
+type Props = {
+ onClick: () => void;
+ disabled?: boolean;
+ variant?: "default" | "primary" | "secondary" | "input" | "dotted" | "tertiary" | "white" | "outline" | "danger-outline" | "default-outline" | "danger" | null | undefined;
+ title?:any;
+ children: any;
+};
+export default function DataTableToolTipButton({ onClick, disabled, variant, title, children }: Props) {
+ const [rotate, setRotate] = useState(false);
+ //const [disabled, setDisabled] = useState(false);
+ const [hovered, setHovered] = useState(false);
+
+ return (
+
+
+
+
+
+ {
+ if (hovered) event.preventDefault();
+ }}
+ >
+
+ {title}
+
+
+
+ );
+}
diff --git a/src/modules/groups/AssignPeerToGroupModal.tsx b/src/modules/groups/AssignPeerToGroupModal.tsx
index 9e15305b..493dbb51 100644
--- a/src/modules/groups/AssignPeerToGroupModal.tsx
+++ b/src/modules/groups/AssignPeerToGroupModal.tsx
@@ -367,6 +367,6 @@ const PeersTableColumns: ColumnDef[] = [
header: ({ column }) => {
return OS;
},
- cell: ({ row }) => ,
+ cell: ({ row }) => ,
},
];
diff --git a/src/modules/peers/PeerOSCell.tsx b/src/modules/peers/PeerOSCell.tsx
index 85df9933..a9f1ad8d 100644
--- a/src/modules/peers/PeerOSCell.tsx
+++ b/src/modules/peers/PeerOSCell.tsx
@@ -13,8 +13,9 @@ import AppleLogo from "@/assets/os-icons/apple.svg";
import FreeBSDLogo from "@/assets/os-icons/FreeBSD.png";
import { getOperatingSystem } from "@/hooks/useOperatingSystem";
import { OperatingSystem } from "@/interfaces/OperatingSystem";
+import { Barcode, Laptop } from "lucide-react";
-export function PeerOSCell({ os }: { os: string }) {
+export function PeerOSCell({ os, serial }: { os: string, serial?: string }) {
return (
@@ -34,13 +35,50 @@ export function PeerOSCell({ os }: { os: string }) {
- {os}
+ }
+ label={"OS"}
+ value={os}
+ />
+ { (serial !== undefined) &&
+ }
+ label={"Serial"}
+ value={serial}
+ />
+ }
);
}
+const ListItem = ({
+ icon,
+ label,
+ value,
+}: {
+ icon: React.ReactNode;
+ label: string;
+ value: string | React.ReactNode;
+}) => {
+ return (
+
+
+ {icon}
+ {label}
+
+
{value}
+
+ );
+};
+
+
export function OSLogo({ os }: { os: string }) {
const icon = useMemo(() => {
return getOperatingSystem(os);
diff --git a/src/modules/peers/PeersTable.tsx b/src/modules/peers/PeersTable.tsx
index 3f98c381..a775e7ab 100644
--- a/src/modules/peers/PeersTable.tsx
+++ b/src/modules/peers/PeersTable.tsx
@@ -14,6 +14,7 @@ import {
ColumnDef,
RowSelectionState,
SortingState,
+ VisibilityState,
} from "@tanstack/react-table";
import { uniqBy } from "lodash";
import { ExternalLinkIcon } from "lucide-react";
@@ -21,6 +22,7 @@ import { usePathname } from "next/navigation";
import React, { useState } from "react";
import { useSWRConfig } from "swr";
import PeerIcon from "@/assets/icons/PeerIcon";
+import DataTableToolTipButton from "@/components/table/DataTableToolTipButton";
import PeerProvider from "@/contexts/PeerProvider";
import { useLoggedInUser } from "@/contexts/UsersProvider";
import { useLocalStorage } from "@/hooks/useLocalStorage";
@@ -40,6 +42,7 @@ import PeerVersionCell from "@/modules/peers/PeerVersionCell";
const PeersTableColumns: ColumnDef[] = [
{
id: "select",
+ enableHiding: false,
header: ({ table }) => (
[] = [
),
enableSorting: false,
- enableHiding: false,
},
{
accessorKey: "name",
+ enableHiding: false,
header: ({ column }) => {
return Name;
},
@@ -82,6 +85,7 @@ const PeersTableColumns: ColumnDef[] = [
accessorFn: (peer) => peer.connected,
},
{
+ id: "ip",
accessorKey: "ip",
sortingFn: "text",
},
@@ -94,6 +98,8 @@ const PeersTableColumns: ColumnDef[] = [
accessorFn: (peer) => (peer.user ? peer.user?.email : "Unknown"),
},
{
+ id: "dns_label",
+ enableHiding: false,
accessorKey: "dns_label",
header: ({ column }) => {
return Address;
@@ -101,11 +107,21 @@ const PeersTableColumns: ColumnDef[] = [
cell: ({ row }) => ,
},
{
+ id: "group_name_strings",
accessorKey: "group_name_strings",
accessorFn: (peer) => peer.groups?.map((g) => g?.name || "").join(", "),
sortingFn: "text",
},
{
+ // used for exact group matching
+ id: "exact_group_name_strings",
+ accessorKey: "exact_group_name_strings",
+ accessorFn: (peer) => peer.groups?.map((g) => g?.name || "").join("|"),
+ sortingFn: "text",
+ filterFn: "equals"
+ },
+ {
+ id: "group_names",
accessorKey: "group_names",
accessorFn: (peer) => peer.groups?.map((g) => g?.name || ""),
sortingFn: "text",
@@ -124,6 +140,7 @@ const PeersTableColumns: ColumnDef[] = [
),
},
{
+ id: "last_seen",
accessorKey: "last_seen",
header: ({ column }) => {
return Last seen;
@@ -132,13 +149,23 @@ const PeersTableColumns: ColumnDef[] = [
cell: ({ row }) => ,
},
{
+ id: "os",
accessorKey: "os",
header: ({ column }) => {
return OS;
},
- cell: ({ row }) => ,
+ cell: ({ row }) => ,
+ },
+ {
+ id: "serial",
+ header: ({ column }) => {
+ return Serial number;
+ },
+ accessorFn: (peer) => peer.serial_number,
+ sortingFn: "text",
},
{
+ id: "version",
accessorKey: "version",
header: ({ column }) => {
return Version;
@@ -165,8 +192,10 @@ const PeersTableColumns: ColumnDef[] = [
},
{
id: "actions",
+ enableHiding: false,
accessorKey: "id",
header: "",
+
cell: ({ row }) => (
@@ -213,6 +242,25 @@ export default function PeersTable({ peers, isLoading, headingTarget }: Props) {
const [selectedRows, setSelectedRows] = useState({});
+ const colVisibility: VisibilityState = {
+ select: !isUser,
+ actions: !isUser,
+ groups: !isUser,
+ connected: false,
+ approval_required: false,
+
+ // hidden, but usefull for lookup
+ serial: false,
+ group_name_strings: false,
+ exact_group_name_strings: false,
+ group_names: false,
+ ip: false,
+ user_name: false,
+ user_email: false,
+ }
+
+ const [resultingColumnVisibility, setColumnVisibility] = useState(colVisibility);
+
const resetSelectedRows = () => {
if (Object.keys(selectedRows).length > 0) {
setSelectedRows({});
@@ -226,6 +274,7 @@ export default function PeersTable({ peers, isLoading, headingTarget }: Props) {
onCanceled={() => setSelectedRows({})}
/>
)}
+ {
+ table.setPageIndex(0);
+ if (table.getColumn("exact_group_name_strings")?.getFilterValue() !== undefined) {
+ table.resetColumnFilters();
+ return;
+ }
+ table.setColumnFilters([
+ {
+ id: "exact_group_name_strings",
+ value: "All"
+ }
+ ])
+ }}
+ variant={table.getColumn("exact_group_name_strings")?.getFilterValue() !== undefined
+ ? "tertiary"
+ : "secondary"}
+ title="filter peers assigned to the uniq group: 'All'"
+ >
+ All group only
+
+
{