-
+ isGroupPage ? (
+
+ }
+ className={"py-4"}
+ title={"This group is not used within any network routes yet"}
+ description={
+ "Assign this group when creating a new route to see them listed here."
+ }
+ >
+
- }
- learnMore={
- <>
- Learn more about
-
+ ) : (
+
}
- target={"_blank"}
- >
- Network Routes
-
-
- >
- }
- />
+ color={"gray"}
+ size={"large"}
+ />
+ }
+ title={"Create New Route"}
+ description={
+ "It looks like you don't have any routes. Access LANs and VPC by adding a network route."
+ }
+ button={
+
+
+
setRouteModal(true)}
+ disabled={!permission.routes.create}
+ >
+
+ Add Route
+
+
+ }
+ learnMore={
+ <>
+ Learn more about
+
+ Network Routes
+
+
+ >
+ }
+ />
+ )
}
rightSide={() => (
<>
{routes && routes?.length > 0 && (
-
+
void;
+ distributionGroups?: Group[];
};
-export default function RouteModal({ children, open, setOpen }: Props) {
+export default function RouteModal({
+ children,
+ open,
+ setOpen,
+ distributionGroups,
+}: Props) {
const { confirm } = useDialog();
const router = useRouter();
const [routePolicyModal, setRoutePolicyModal] = useState(false);
@@ -116,6 +123,7 @@ export default function RouteModal({ children, open, setOpen }: Props) {
await handleCreatePolicyPrompt(r);
setOpen?.(false);
}}
+ distributionGroups={distributionGroups}
/>
)}
@@ -139,6 +147,7 @@ type ModalProps = {
peer?: Peer;
exitNode?: boolean;
isFirstExitNode?: boolean;
+ distributionGroups?: Group[];
};
export function RouteModalContent({
@@ -146,6 +155,7 @@ export function RouteModalContent({
peer,
exitNode,
isFirstExitNode = false,
+ distributionGroups,
}: ModalProps) {
const { createRoute } = useRoutes();
const [tab, setTab] = useState(
@@ -207,7 +217,7 @@ export function RouteModalContent({
* Distribution Groups
*/
const [groups, setGroups, { getGroupsToUpdate }] = useGroupHelper({
- initial: [],
+ initial: distributionGroups ?? [],
});
/**
@@ -721,17 +731,19 @@ export function RouteModalContent({
/>
{exitNode && (
-
-
- Auto Apply Route
- >
- }
- helpText={"Automatically apply this exit node to your distribution groups. This requires NetBird client v0.55.0 or higher."}
- />
+
+
+ Auto Apply Route
+ >
+ }
+ helpText={
+ "Automatically apply this exit node to your distribution groups. This requires NetBird client v0.55.0 or higher."
+ }
+ />
)}
{!exitNode && (
diff --git a/src/modules/settings/GroupsActionCell.tsx b/src/modules/settings/GroupsActionCell.tsx
deleted file mode 100644
index cca3fc8..0000000
--- a/src/modules/settings/GroupsActionCell.tsx
+++ /dev/null
@@ -1,89 +0,0 @@
-import Button from "@components/Button";
-import FullTooltip from "@components/FullTooltip";
-import { notify } from "@components/Notification";
-import { useApiCall } from "@utils/api";
-import { Trash2 } from "lucide-react";
-import React, { useMemo } from "react";
-import { useSWRConfig } from "swr";
-import { useDialog } from "@/contexts/DialogProvider";
-import { usePermissions } from "@/contexts/PermissionsProvider";
-import { SetupKey } from "@/interfaces/SetupKey";
-import { useGroupIdentification } from "@/modules/groups/useGroupIdentification";
-import { GroupUsage } from "@/modules/settings/useGroupsUsage";
-
-type Props = {
- group: GroupUsage;
- in_use: boolean;
-};
-export default function GroupsActionCell({ group, in_use }: Readonly) {
- const { permission } = usePermissions();
- const { confirm } = useDialog();
- const deleteRequest = useApiCall("/groups/" + group.id);
- const { mutate } = useSWRConfig();
-
- const handleRevoke = async () => {
- notify({
- title: "Group: " + group.name,
- description: "Group was successfully deleted.",
- promise: deleteRequest.del().then(() => {
- mutate("/groups");
- }),
- loadingMessage: "Deleting the group...",
- });
- };
-
- const handleConfirm = async () => {
- const choice = await confirm({
- title: `Delete '${group.name}'?`,
- description:
- "Are you sure you want to delete this group? This action cannot be undone.",
- confirmText: "Delete",
- cancelText: "Cancel",
- type: "danger",
- });
- if (!choice) return;
- handleRevoke().then();
- };
-
- const { isRegularGroup, isJWTGroup } = useGroupIdentification({
- id: group?.id,
- issued: group?.issued,
- });
-
- const isDisabled = useMemo(() => {
- if (!permission.groups.delete) return true;
- if (in_use) return true;
- if (isJWTGroup) return false;
- return !isRegularGroup;
- }, [permission, in_use, isJWTGroup, isRegularGroup]);
-
- const getDisabledText = () => {
- if (isRegularGroup) {
- return "Remove dependencies to this group to delete it.";
- } else if (isJWTGroup) {
- return "This group is issued by JWT and cannot be deleted.";
- } else {
- return "This group is issued by an IdP and cannot be deleted";
- }
- };
-
- return (
-
- {getDisabledText()}
}
- interactive={false}
- disabled={!isDisabled}
- >
-
-
- Delete
-
-
-
- );
-}
diff --git a/src/modules/settings/GroupsCountCell.tsx b/src/modules/settings/GroupsCountCell.tsx
deleted file mode 100644
index b555d26..0000000
--- a/src/modules/settings/GroupsCountCell.tsx
+++ /dev/null
@@ -1,38 +0,0 @@
-import Badge from "@components/Badge";
-import FullTooltip from "@components/FullTooltip";
-import { cn } from "@utils/helpers";
-import React from "react";
-
-type Props = {
- icon: React.ReactNode;
- count: number;
- groupName: string;
- text?: string;
-};
-export default function GroupsCountCell({
- icon,
- count,
- groupName,
- text,
-}: Props) {
- return (
-
- Group {groupName} {" "}
- is used in {count} {" "}
- {text}
-
- }
- >
-