Compare commits

..
42 changed files with 317 additions and 1454 deletions

No files matched your search

-347
View File
@@ -14,7 +14,6 @@
"@radix-ui/react-collapsible": "^1.0.3",
"@radix-ui/react-dialog": "^1.0.5",
"@radix-ui/react-dropdown-menu": "^2.0.6",
"@radix-ui/react-hover-card": "^1.1.4",
"@radix-ui/react-label": "^2.0.2",
"@radix-ui/react-popover": "^1.0.7",
"@radix-ui/react-radio-group": "^1.1.3",
@@ -922,352 +921,6 @@
}
}
},
"node_modules/@radix-ui/react-hover-card": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/@radix-ui/react-hover-card/-/react-hover-card-1.1.4.tgz",
"integrity": "sha512-QSUUnRA3PQ2UhvoCv3eYvMnCAgGQW+sTu86QPuNb+ZMi+ZENd6UWpiXbcWDQ4AEaKF9KKpCHBeaJz9Rw6lRlaQ==",
"license": "MIT",
"dependencies": {
"@radix-ui/primitive": "1.1.1",
"@radix-ui/react-compose-refs": "1.1.1",
"@radix-ui/react-context": "1.1.1",
"@radix-ui/react-dismissable-layer": "1.1.3",
"@radix-ui/react-popper": "1.2.1",
"@radix-ui/react-portal": "1.1.3",
"@radix-ui/react-presence": "1.1.2",
"@radix-ui/react-primitive": "2.0.1",
"@radix-ui/react-use-controllable-state": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-hover-card/node_modules/@radix-ui/primitive": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.1.tgz",
"integrity": "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA==",
"license": "MIT"
},
"node_modules/@radix-ui/react-hover-card/node_modules/@radix-ui/react-arrow": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.1.tgz",
"integrity": "sha512-NaVpZfmv8SKeZbn4ijN2V3jlHA9ngBG16VnIIm22nUR0Yk8KUALyBxT3KYEUnNuch9sTE8UTsS3whzBgKOL30w==",
"license": "MIT",
"dependencies": {
"@radix-ui/react-primitive": "2.0.1"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-hover-card/node_modules/@radix-ui/react-compose-refs": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz",
"integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==",
"license": "MIT",
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-hover-card/node_modules/@radix-ui/react-context": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz",
"integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==",
"license": "MIT",
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-hover-card/node_modules/@radix-ui/react-dismissable-layer": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.3.tgz",
"integrity": "sha512-onrWn/72lQoEucDmJnr8uczSNTujT0vJnA/X5+3AkChVPowr8n1yvIKIabhWyMQeMvvmdpsvcyDqx3X1LEXCPg==",
"license": "MIT",
"dependencies": {
"@radix-ui/primitive": "1.1.1",
"@radix-ui/react-compose-refs": "1.1.1",
"@radix-ui/react-primitive": "2.0.1",
"@radix-ui/react-use-callback-ref": "1.1.0",
"@radix-ui/react-use-escape-keydown": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-hover-card/node_modules/@radix-ui/react-popper": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.1.tgz",
"integrity": "sha512-3kn5Me69L+jv82EKRuQCXdYyf1DqHwD2U/sxoNgBGCB7K9TRc3bQamQ+5EPM9EvyPdli0W41sROd+ZU1dTCztw==",
"license": "MIT",
"dependencies": {
"@floating-ui/react-dom": "^2.0.0",
"@radix-ui/react-arrow": "1.1.1",
"@radix-ui/react-compose-refs": "1.1.1",
"@radix-ui/react-context": "1.1.1",
"@radix-ui/react-primitive": "2.0.1",
"@radix-ui/react-use-callback-ref": "1.1.0",
"@radix-ui/react-use-layout-effect": "1.1.0",
"@radix-ui/react-use-rect": "1.1.0",
"@radix-ui/react-use-size": "1.1.0",
"@radix-ui/rect": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-hover-card/node_modules/@radix-ui/react-portal": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.3.tgz",
"integrity": "sha512-NciRqhXnGojhT93RPyDaMPfLH3ZSl4jjIFbZQ1b/vxvZEdHsBZ49wP9w8L3HzUQwep01LcWtkUvm0OVB5JAHTw==",
"license": "MIT",
"dependencies": {
"@radix-ui/react-primitive": "2.0.1",
"@radix-ui/react-use-layout-effect": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-hover-card/node_modules/@radix-ui/react-presence": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.2.tgz",
"integrity": "sha512-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg==",
"license": "MIT",
"dependencies": {
"@radix-ui/react-compose-refs": "1.1.1",
"@radix-ui/react-use-layout-effect": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-hover-card/node_modules/@radix-ui/react-primitive": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.1.tgz",
"integrity": "sha512-sHCWTtxwNn3L3fH8qAfnF3WbUZycW93SM1j3NFDzXBiz8D6F5UTTy8G1+WFEaiCdvCVRJWj6N2R4Xq6HdiHmDg==",
"license": "MIT",
"dependencies": {
"@radix-ui/react-slot": "1.1.1"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-hover-card/node_modules/@radix-ui/react-slot": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.1.tgz",
"integrity": "sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g==",
"license": "MIT",
"dependencies": {
"@radix-ui/react-compose-refs": "1.1.1"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-hover-card/node_modules/@radix-ui/react-use-callback-ref": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz",
"integrity": "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==",
"license": "MIT",
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-hover-card/node_modules/@radix-ui/react-use-controllable-state": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz",
"integrity": "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==",
"license": "MIT",
"dependencies": {
"@radix-ui/react-use-callback-ref": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-hover-card/node_modules/@radix-ui/react-use-escape-keydown": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz",
"integrity": "sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw==",
"license": "MIT",
"dependencies": {
"@radix-ui/react-use-callback-ref": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-hover-card/node_modules/@radix-ui/react-use-layout-effect": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz",
"integrity": "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==",
"license": "MIT",
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-hover-card/node_modules/@radix-ui/react-use-rect": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.0.tgz",
"integrity": "sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ==",
"license": "MIT",
"dependencies": {
"@radix-ui/rect": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-hover-card/node_modules/@radix-ui/react-use-size": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.0.tgz",
"integrity": "sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw==",
"license": "MIT",
"dependencies": {
"@radix-ui/react-use-layout-effect": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-hover-card/node_modules/@radix-ui/rect": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.0.tgz",
"integrity": "sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg==",
"license": "MIT"
},
"node_modules/@radix-ui/react-id": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.0.1.tgz",
-1
View File
@@ -19,7 +19,6 @@
"@radix-ui/react-collapsible": "^1.0.3",
"@radix-ui/react-dialog": "^1.0.5",
"@radix-ui/react-dropdown-menu": "^2.0.6",
"@radix-ui/react-hover-card": "^1.1.4",
"@radix-ui/react-label": "^2.0.2",
"@radix-ui/react-popover": "^1.0.7",
"@radix-ui/react-radio-group": "^1.1.3",
+4 -1
View File
@@ -14,6 +14,7 @@ import PeersProvider from "@/contexts/PeersProvider";
import RoutesProvider from "@/contexts/RoutesProvider";
import { Route } from "@/interfaces/Route";
import PageContainer from "@/layouts/PageContainer";
import { NetworkRoutesDeprecationInfo } from "@/modules/networks/misc/NetworkRoutesDeprecationInfo";
import useGroupedRoutes from "@/modules/route-group/useGroupedRoutes";
const NetworkRoutesTable = lazy(
@@ -39,7 +40,9 @@ export default function NetworkRoutes() {
icon={<NetworkRoutesIcon size={13} />}
/>
</Breadcrumbs>
<h1 ref={headingRef}>Network Routes</h1>
<h1 ref={headingRef}>
Network Routes <NetworkRoutesDeprecationInfo size={18} />
</h1>
<Paragraph>
Network routes allow you to access other networks like LANs and
VPCs without installing NetBird on every resource.
+3 -6
View File
@@ -31,15 +31,12 @@ export default function Networks() {
</Breadcrumbs>
<h1 ref={headingRef}>Networks</h1>
<Paragraph>
Networks allow you to access internal resources in LANs and VPCs without
installing NetBird on every machine.
Networks allow you to access other resources like LANs and VPCs
without installing NetBird on every device.
</Paragraph>
<Paragraph>
Learn more about
<InlineLink
href={"https://docs.netbird.io/how-to/networks"}
target={"_blank"}
>
<InlineLink href={"https://docs.netbird.io/how-to/networks"} target={"_blank"}>
Networks
<ExternalLinkIcon size={12} />
</InlineLink>
-1
View File
@@ -316,7 +316,6 @@ function UserInformationCard({ user }: { user: User }) {
<>
{!user.is_current && user.role != Role.Owner && (
<Card.ListItem
tooltip={false}
label={
<>
<Ban size={16} />
+6 -24
View File
@@ -30,7 +30,7 @@ import * as React from "react";
import { Fragment, useEffect, useMemo, useState } from "react";
import { useGroups } from "@/contexts/GroupsProvider";
import { useElementSize } from "@/hooks/useElementSize";
import type { Group, GroupPeer, GroupResource } from "@/interfaces/Group";
import type {Group, GroupPeer, GroupResource} from "@/interfaces/Group";
import { NetworkResource } from "@/interfaces/Network";
import type { Peer } from "@/interfaces/Peer";
@@ -48,7 +48,6 @@ interface MultiSelectProps {
showRoutes?: boolean;
disabledGroups?: Group[];
dataCy?: string;
showResourceCounter?: boolean;
}
export function PeerGroupSelector({
onChange,
@@ -64,7 +63,6 @@ export function PeerGroupSelector({
showRoutes = false,
disabledGroups,
dataCy = "group-selector-dropdown",
showResourceCounter = true,
}: Readonly<MultiSelectProps>) {
const { groups, dropdownOptions, setDropdownOptions, addDropdownOptions } =
useGroups();
@@ -107,34 +105,20 @@ export function PeerGroupSelector({
const groupPeers: GroupPeer[] | undefined =
(group?.peers as GroupPeer[]) || [];
const groupResources: GroupResource[] | undefined =
(group?.resources as GroupResource[]) || [];
(group?.resources as GroupResource[]) || [];
if (peer) groupPeers?.push({ id: peer?.id as string, name: peer?.name });
if (!group && !option) {
addDropdownOptions([
{ name: name, peers: groupPeers, resources: groupResources },
]);
addDropdownOptions([{ name: name, peers: groupPeers, resources: groupResources }]);
}
if (max == 1 && values.length == 1) {
onChange([
{
name: name,
id: group?.id,
peers: groupPeers,
resources: groupResources,
},
]);
onChange([{ name: name, id: group?.id, peers: groupPeers, resources: groupResources }]);
} else {
onChange((previous) => [
...previous,
{
name: name,
id: group?.id,
peers: groupPeers,
resources: groupResources,
},
{ name: name, id: group?.id, peers: groupPeers, resources: groupResources },
]);
}
@@ -412,9 +396,7 @@ export function PeerGroupSelector({
<AccessControlGroupCount group_id={option.id} />
)}
{showResourceCounter && (
<ResourcesCounter group={option} />
)}
<ResourcesCounter group={option} />
<div
className={
+7 -9
View File
@@ -166,17 +166,15 @@ export function PeerSelector({
placeholder={"Search for peers by name or ip..."}
/>
{unfilteredItems.length == 0 && !search && (
<div className={"max-w-xs mx-auto"}>
<DropdownInfoText>
{
"Seems like you don't have any Linux peers to assign as a routing peer."
}
</DropdownInfoText>
</div>
{unfilteredItems.length == 0 && (
<DropdownInfoText>
{
"Seems like you don't have any linux peers to assign as a routing peer."
}
</DropdownInfoText>
)}
{filteredItems.length == 0 && search != "" && (
{filteredItems.length == 0 && (
<DropdownInfoText>
There are no peers matching your search.
</DropdownInfoText>
+2 -4
View File
@@ -60,12 +60,10 @@ export default function SidebarItem({
<li className={"px-4 cursor-pointer"}>
<button
className={classNames(
"rounded-lg text-[.87rem] w-full ",
"rounded-lg text-[.95rem] w-full ",
"font-normal ",
className,
isChild
? "pl-7 pr-2 py-[.45rem] mt-1 mb-0.5"
: "py-[.45rem] px-3",
isChild ? "pl-7 pr-2 py-2 mt-1 mb-0.5" : "py-2 px-3",
isActive
? "text-gray-900 bg-gray-200 dark:text-white dark:bg-nb-gray-900"
: "text-gray-600 hover:bg-gray-200 dark:text-nb-gray-400 dark:hover:bg-nb-gray-900/50",
+7 -27
View File
@@ -4,18 +4,9 @@ import React from "react";
type Props = {
children: React.ReactNode;
className?: string;
horizontal?: boolean;
};
export default function Steps({
children,
className,
horizontal = false,
}: Readonly<Props>) {
return (
<div className={cn("pt-4", horizontal && "flex", className)}>
{children}
</div>
);
export default function Steps({ children, className }: Props) {
return <div className={cn("pt-4", className)}>{children}</div>;
}
type StepProps = {
@@ -23,32 +14,21 @@ type StepProps = {
step: number;
line?: boolean;
center?: boolean;
horizontal?: boolean;
};
const Step = ({
children,
step,
line = true,
center = false,
horizontal,
}: StepProps) => {
const Step = ({ children, step, line = true, center = false }: StepProps) => {
return (
<div
className={cn(
"flex gap-4 items-start justify-start relative pb-6 -mx-1.5 group px-[2px]",
"flex gap-4 items-start min-w-full justify-start relative pb-6 -mx-1.5 group px-[2px]",
center && "items-center",
horizontal ? "flex-col items-center" : "min-w-full",
)}
>
{line && (
<span
className={cn(
"bg-nb-gray-100 dark:bg-nb-gray-800 z-0 transition-all",
horizontal
? "w-full h-[2px] absolute mt-[16px] transform translate-x-1/2"
: "h-full w-[2px] absolute left-0 ml-[18px]",
)}
className={
"h-full w-[2px] bg-nb-gray-100 dark:bg-nb-gray-800 absolute left-0 ml-[18px] z-0 transition-all"
}
></span>
)}
+12 -4
View File
@@ -1,6 +1,5 @@
import Badge from "@components/Badge";
import { NewBadge } from "@components/ui/NewBadge";
import TruncatedText from "@components/ui/TruncatedText";
import TextWithTooltip from "@components/ui/TextWithTooltip";
import { cn } from "@utils/helpers";
import { FolderGit2, XIcon } from "lucide-react";
import * as React from "react";
@@ -38,9 +37,18 @@ export default function GroupBadge({
>
<FolderGit2 size={12} className={"shrink-0"} />
<TruncatedText text={group?.name || ""} maxChars={20} />
<TextWithTooltip text={group?.name || ""} maxChars={20} />
{children}
{isNew && showNewBadge && <NewBadge />}
{isNew && showNewBadge && (
<span
className={
"text-[7px] relative top-[.25px] leading-[0] bg-green-900 border border-green-500/20 py-1.5 px-1 rounded-[3px] text-green-400"
}
>
NEW
</span>
)}
{showX && (
<XIcon
size={12}
-16
View File
@@ -1,16 +0,0 @@
import * as React from "react";
type Props = {
text?: string;
};
export const NewBadge = ({ text = "NEW" }: Props) => {
return (
<span
className={
"text-[7px] relative top-[.25px] leading-[0] bg-green-900 border border-green-500/20 py-1.5 px-1 rounded-[3px] text-green-400"
}
>
{text}
</span>
);
};
-78
View File
@@ -1,78 +0,0 @@
import * as HoverCard from "@radix-ui/react-hover-card";
import { cn } from "@utils/helpers";
import React, { useMemo, useState } from "react";
type Props = {
text?: string;
className?: string;
maxChars?: number;
hideTooltip?: boolean;
};
export default function TruncatedText({
text,
className,
maxChars = 40,
hideTooltip = false,
}: Props) {
const charCount = useMemo(() => {
if (!text) return 0;
return text.length;
}, [text]);
const isDisabled = charCount <= maxChars || hideTooltip;
const [open, setOpen] = useState(false);
if (isDisabled) {
return (
<div
className={"w-full min-w-0 inline-block"}
style={{
maxWidth: `${maxChars - 2}ch`,
}}
>
<div className={cn(className, "truncate")}>{text}</div>
</div>
);
}
return (
<HoverCard.Root
openDelay={650}
closeDelay={100}
open={open}
onOpenChange={setOpen}
>
<HoverCard.Trigger asChild={true}>
<div
className={"w-full min-w-0 inline-block"}
style={{
maxWidth: `${maxChars - 2}ch`,
}}
>
<div className={cn(className, "truncate")}>{text}</div>
</div>
</HoverCard.Trigger>
<HoverCard.Portal>
<HoverCard.Content
onMouseLeave={() => setOpen(false)}
onMouseEnter={() => setOpen(false)}
alignOffset={20}
sideOffset={4}
className={cn(
"z-[9999] overflow-hidden rounded-md border border-neutral-200 bg-white text-sm text-neutral-950 shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 dark:border-nb-gray-930 dark:bg-nb-gray-940 dark:text-neutral-50",
className,
"px-3 py-1.5",
)}
>
<div className={"text-neutral-300 flex flex-col gap-1"}>
<div className={"max-w-xs break-all whitespace-normal text-xs"}>
{text}
</div>
</div>
</HoverCard.Content>
</HoverCard.Portal>
</HoverCard.Root>
);
}
-2
View File
@@ -16,7 +16,6 @@ export interface NetworkRouter {
peer_groups?: string[];
metric: number;
masquerade: boolean;
enabled: boolean;
}
export interface NetworkResource {
@@ -26,5 +25,4 @@ export interface NetworkResource {
address: string;
groups?: string[] | Group[];
type?: "domain" | "host" | "subnet";
enabled: boolean;
}
@@ -281,7 +281,6 @@ export function AccessControlModalContent({
onChange={setSourceGroups}
values={sourceGroups}
saveGroupAssignments={useSave}
showResourceCounter={false}
/>
</div>
<PolicyDirection
@@ -392,7 +391,9 @@ export function AccessControlModalContent({
<Paragraph className={"text-sm mt-auto"}>
Learn more about
<InlineLink
href={"https://docs.netbird.io/how-to/manage-network-access"}
href={
"https://docs.netbird.io/how-to/manage-network-access"
}
target={"_blank"}
>
Access Controls
-17
View File
@@ -37,22 +37,6 @@ const ActivityFeedColumnsTable: ColumnDef<ActivityEvent>[] = [
filterFn: "arrIncludesSomeExact",
cell: ({ row }) => <ActivityEntryRow event={row.original} />,
},
{
id: "activity_text",
accessorFn: (event) => {
try {
if (event.meta) {
return Object.keys(event.meta)
.map((key) => {
return `${event?.meta[key]}`;
})
.join(" ");
}
} catch (error) {
return "";
}
},
},
{
accessorKey: "timestamp",
id: "timestamp",
@@ -119,7 +103,6 @@ export default function ActivityTable({
columnVisibility={{
timestamp: false,
name: false,
activity_text: false,
initiator_email: false,
}}
getStartedCard={
+4 -40
View File
@@ -10,7 +10,6 @@ import { Network, NetworkResource, NetworkRouter } from "@/interfaces/Network";
import { AccessControlModalContent } from "@/modules/access-control/AccessControlModal";
import NetworkModal from "@/modules/networks/NetworkModal";
import NetworkResourceModal from "@/modules/networks/resources/NetworkResourceModal";
import { ResourceGroupModal } from "@/modules/networks/resources/ResourceGroupModal";
import NetworkRoutingPeerModal from "@/modules/networks/routing-peers/NetworkRoutingPeerModal";
type Props = {
@@ -24,10 +23,6 @@ const NetworksContext = React.createContext(
openEditNetworkModal: (network: Network) => void;
openCreateNetworkModal: () => void;
openResourceModal: (network: Network, resource?: NetworkResource) => void;
openResourceGroupModal: (
network: Network,
resource?: NetworkResource,
) => void;
openPolicyModal: (network?: Network, resource?: NetworkResource) => void;
deleteNetwork: (network: Network) => void;
deleteResource: (network: Network, resource: NetworkResource) => void;
@@ -54,7 +49,6 @@ export const NetworkProvider = ({ children, network }: Props) => {
const [routingPeerModal, setRoutingPeerModal] = useState(false);
const [networkModal, setNetworkModal] = useState(false);
const [resourceModal, setResourceModal] = useState(false);
const [resourceGroupModal, setResourceGroupModal] = useState(false);
const [policyModal, setPolicyModal] = useState(false);
const openAddRoutingPeerModal = (
@@ -82,15 +76,6 @@ export const NetworkProvider = ({ children, network }: Props) => {
setResourceModal(true);
};
const openResourceGroupModal = (
network: Network,
resource?: NetworkResource,
) => {
setCurrentNetwork(network);
resource && setCurrentResource(resource);
setResourceGroupModal(true);
};
const openPolicyModal = (network?: Network, resource?: NetworkResource) => {
setPolicyDefaultSettings({
destinationGroups: resource?.groups,
@@ -232,7 +217,6 @@ export const NetworkProvider = ({ children, network }: Props) => {
openEditNetworkModal,
openCreateNetworkModal,
openResourceModal,
openResourceGroupModal,
openPolicyModal,
deleteNetwork,
deleteResource,
@@ -248,7 +232,7 @@ export const NetworkProvider = ({ children, network }: Props) => {
network={currentNetwork}
onCreated={async (network) => {
mutate("/networks");
await askForResource(network);
await askForRoutingPeer(network);
}}
onUpdated={() => {
mutate("/networks");
@@ -266,15 +250,13 @@ export const NetworkProvider = ({ children, network }: Props) => {
initialDestinationGroups={policyDefaultSettings?.destinationGroups}
initialName={policyDefaultSettings?.name}
initialDescription={policyDefaultSettings?.description}
onSuccess={async (p) => {
onSuccess={(p) => {
setPolicyModal(false);
setPolicyDefaultSettings(undefined);
mutate("/networks");
if (network) {
mutate(`/networks/${network.id}/resources`);
mutate(`/networks/${network.id}`);
} else {
currentNetwork && (await askForRoutingPeer(currentNetwork));
}
}}
/>
@@ -293,6 +275,8 @@ export const NetworkProvider = ({ children, network }: Props) => {
if (network) {
mutate(`/networks/${currentNetwork.id}/routers`);
mutate(`/networks/${network.id}`);
} else {
await askForResource(currentNetwork);
}
}}
onUpdated={async () => {
@@ -310,26 +294,6 @@ export const NetworkProvider = ({ children, network }: Props) => {
setRoutingPeerModal(state);
}}
/>
<ResourceGroupModal
network={currentNetwork}
resource={currentResource}
open={resourceGroupModal}
onOpenChange={(state) => {
setCurrentResource(undefined);
setResourceGroupModal(state);
}}
onUpdated={() => {
setResourceGroupModal(false);
setCurrentResource(undefined);
mutate("/groups");
if (network) {
mutate(`/networks/${network.id}/resources`);
mutate(`/networks/${network.id}`);
}
}}
/>
<NetworkResourceModal
network={currentNetwork}
resource={currentResource}
@@ -60,7 +60,10 @@ export const NetworkInformationSquare = ({
{name}
</p>
<DescriptionWithTooltip
className={cn("text-left", size == "lg" && "text-md mt-0.5")}
className={cn(
"text-left",
size == "lg" && "text-md leading-none mt-0.5",
)}
maxChars={24}
text={description}
/>
+13 -12
View File
@@ -1,26 +1,27 @@
import SidebarItem from "@components/SidebarItem";
import { NewBadge } from "@components/ui/NewBadge";
import * as React from "react";
import NetworkRoutesIcon from "@/assets/icons/NetworkRoutesIcon";
import { NetworkRoutesDeprecationInfo } from "@/modules/networks/misc/NetworkRoutesDeprecationInfo";
export const NetworkNavigation = () => {
return (
<>
<SidebarItem
icon={<NetworkRoutesIcon />}
label="Networks"
collapsible
exactPathMatch={false}
>
<SidebarItem label="Networks" isChild href={"/networks"} />
<SidebarItem
icon={<NetworkRoutesIcon />}
label={
<div className={"flex items-center gap-2"}>
Networks
<NewBadge />
<div className={"flex items-center"}>
Network Routes
<NetworkRoutesDeprecationInfo />
</div>
}
href={"/networks"}
/>
<SidebarItem
icon={<NetworkRoutesIcon />}
isChild
href={"/network-routes"}
label={"Network Routes"}
/>
</>
</SidebarItem>
);
};
@@ -1,7 +1,6 @@
"use client";
import Button from "@components/Button";
import FancyToggleSwitch from "@components/FancyToggleSwitch";
import HelpText from "@components/HelpText";
import InlineLink from "@components/InlineLink";
import { Input } from "@components/Input";
@@ -18,12 +17,7 @@ import Paragraph from "@components/Paragraph";
import { PeerGroupSelector } from "@components/PeerGroupSelector";
import Separator from "@components/Separator";
import { useApiCall } from "@utils/api";
import {
ExternalLinkIcon,
PlusCircle,
Power,
WorkflowIcon,
} from "lucide-react";
import { ExternalLinkIcon, PlusCircle, WorkflowIcon } from "lucide-react";
import React, { useMemo, useState } from "react";
import { Network, NetworkResource } from "@/interfaces/Network";
import useGroupHelper from "@/modules/groups/useGroupHelper";
@@ -85,9 +79,6 @@ export function ResourceModalContent({
const [groups, setGroups, { save: saveGroups }] = useGroupHelper({
initial: resource?.groups || [],
});
const [enabled, setEnabled] = useState<boolean>(
resource ? resource.enabled : true,
);
const createResource = async () => {
const savedGroups = await saveGroups();
@@ -100,7 +91,6 @@ export function ResourceModalContent({
description,
address,
groups: savedGroups.map((g) => g.id),
enabled,
}).then((r) => {
onCreated?.(r);
}),
@@ -118,7 +108,6 @@ export function ResourceModalContent({
description,
address,
groups: savedGroups.map((g) => g.id),
enabled,
}).then((r) => {
onUpdated?.(r);
}),
@@ -162,34 +151,17 @@ export function ResourceModalContent({
<div>
<Label>Assigned Groups</Label>
<HelpText>
Add this resource to groups and use them as destinations when
creating policies
Control access to this resource by assigning it to groups
</HelpText>
<PeerGroupSelector onChange={setGroups} values={groups} />
</div>
<div className={"mt-3"}>
<FancyToggleSwitch
value={enabled}
onChange={setEnabled}
label={
<>
<Power size={15} />
Enable Resource
</>
}
helpText={"Use this switch to enable or disable the resource."}
/>
</div>
</div>
<ModalFooter className={"items-center"}>
<div className={"w-full"}>
<Paragraph className={"text-sm mt-auto"}>
Learn more about
<InlineLink
href={"https://docs.netbird.io/how-to/networks#resources"}
target={"_blank"}
>
<InlineLink href={"https://docs.netbird.io/how-to/networks#resources"} target={"_blank"}>
Resources
<ExternalLinkIcon size={12} />
</InlineLink>
@@ -1,11 +1,5 @@
import Button from "@components/Button";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@components/DropdownMenu";
import { MoreVertical, SquarePenIcon, Trash2 } from "lucide-react";
import { SquarePenIcon, Trash2 } from "lucide-react";
import * as React from "react";
import { NetworkResource } from "@/interfaces/Network";
import { useNetworksContext } from "@/modules/networks/NetworkProvider";
@@ -17,45 +11,29 @@ export const ResourceActionCell = ({ resource }: Props) => {
const { deleteResource, network, openResourceModal } = useNetworksContext();
return (
<div className={"flex justify-end"}>
<DropdownMenu modal={false}>
<DropdownMenuTrigger
asChild={true}
onClick={(e) => {
e.stopPropagation();
e.preventDefault();
}}
>
<Button variant={"secondary"} className={"!px-3"}>
<MoreVertical size={16} className={"shrink-0"} />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-auto" align="end">
<DropdownMenuItem
onClick={() => {
if (!network) return;
openResourceModal(network, resource);
}}
>
<div className={"flex gap-3 items-center"}>
<SquarePenIcon size={14} className={"shrink-0"} />
Edit
</div>
</DropdownMenuItem>
<DropdownMenuItem
onClick={() => {
if (!network) return;
deleteResource(network, resource);
}}
variant={"danger"}
>
<div className={"flex gap-3 items-center"}>
<Trash2 size={14} className={"shrink-0"} />
Remove
</div>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
<div className={"flex justify-end pr-4"}>
<Button
variant={"default-outline"}
size={"sm"}
onClick={() => {
if (!network) return;
openResourceModal(network, resource);
}}
>
<SquarePenIcon size={16} />
Edit
</Button>
<Button
variant={"danger-outline"}
size={"sm"}
onClick={() => {
if (!network) return;
deleteResource(network, resource);
}}
>
<Trash2 size={16} />
Remove
</Button>
</div>
);
};
Loaded 20 of 42 files, more files were not shown because too many files have changed in this diff. Show more