misc: move gateway and relay to networking page

This commit is contained in:
Sheen Capadngan
2025-09-21 10:58:45 +08:00
parent edc93d5b06
commit e3648da9cb
17 changed files with 596 additions and 654 deletions

View File

@@ -1,11 +1,10 @@
import {
faBook,
faCog,
faDoorClosed,
faInfinity,
faMoneyBill,
faNetworkWired,
faPlug,
faRoute,
faShare,
faTable,
faUsers,
@@ -125,26 +124,16 @@ export const OrgSidebar = ({ isHidden }: Props) => {
</MenuItem>
)}
</Link>
<Link to="/organization/gateways">
</MenuGroup>
<MenuGroup title="Others">
<Link to="/organization/networking">
{({ isActive }) => (
<MenuItem isSelected={isActive}>
<div className="mx-1 flex gap-2">
<div className="w-6">
<FontAwesomeIcon icon={faDoorClosed} className="mr-4" />
<FontAwesomeIcon icon={faNetworkWired} className="mr-4" />
</div>
Gateways
</div>
</MenuItem>
)}
</Link>
<Link to="/organization/relays">
{({ isActive }) => (
<MenuItem isSelected={isActive}>
<div className="mx-1 flex gap-2">
<div className="w-6">
<FontAwesomeIcon icon={faRoute} className="mr-4" />
</div>
Relays
Networking
</div>
</MenuItem>
)}

View File

@@ -1,267 +0,0 @@
import { useState } from "react";
import { Helmet } from "react-helmet";
import {
faArrowUpRightFromSquare,
faBookOpen,
faCopy,
faDoorClosed,
faEdit,
faEllipsisV,
faInfoCircle,
faMagnifyingGlass,
faSearch,
faTrash
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { useQuery } from "@tanstack/react-query";
import { formatRelative } from "date-fns";
import { createNotification } from "@app/components/notifications";
import { OrgPermissionCan } from "@app/components/permissions";
import {
DeleteActionModal,
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
EmptyState,
IconButton,
Input,
Modal,
ModalContent,
PageHeader,
Table,
TableContainer,
TableSkeleton,
TBody,
Td,
Th,
THead,
Tooltip,
Tr
} from "@app/components/v2";
import {
OrgGatewayPermissionActions,
OrgPermissionAppConnectionActions,
OrgPermissionSubjects
} from "@app/context/OrgPermissionContext/types";
import { withPermission } from "@app/hoc";
import { usePopUp } from "@app/hooks";
import { gatewaysQueryKeys, useDeleteGatewayById } from "@app/hooks/api/gateways";
import { useDeleteGatewayV2ById } from "@app/hooks/api/gateways-v2";
import { EditGatewayDetailsModal } from "./components/EditGatewayDetailsModal";
export const GatewayListPage = withPermission(
() => {
const [search, setSearch] = useState("");
const { data: gateways, isPending: isGatewaysLoading } = useQuery(gatewaysQueryKeys.list());
const { popUp, handlePopUpOpen, handlePopUpToggle } = usePopUp([
"deleteGateway",
"editDetails"
] as const);
const deleteGatewayById = useDeleteGatewayById();
const deleteGatewayV2ById = useDeleteGatewayV2ById();
const handleDeleteGateway = async () => {
const data = popUp.deleteGateway.data as { id: string; isV1: boolean };
if (data.isV1) {
await deleteGatewayById.mutateAsync(data.id);
} else {
await deleteGatewayV2ById.mutateAsync(data.id);
}
handlePopUpToggle("deleteGateway");
createNotification({
type: "success",
text: "Successfully deleted gateway"
});
};
const filteredGateway = gateways?.filter((el) =>
el.name.toLowerCase().includes(search.toLowerCase())
);
return (
<div className="bg-bunker-800">
<Helmet>
<title>Infisical | Gateways</title>
<meta property="og:image" content="/images/message.png" />
</Helmet>
<div className="flex w-full justify-center bg-bunker-800 text-white">
<div className="w-full max-w-7xl">
<PageHeader
className="w-full"
title={
<div className="flex w-full items-center">
<span>Gateways</span>
<a
className="-mt-1.5"
href="https://infisical.com/docs/documentation/platform/gateways/overview"
target="_blank"
rel="noopener noreferrer"
>
<div className="ml-2 inline-block rounded-md bg-yellow/20 px-1.5 text-sm font-normal text-yellow opacity-80 hover:opacity-100">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
<span>Docs</span>
<FontAwesomeIcon
icon={faArrowUpRightFromSquare}
className="mb-[0.07rem] ml-1.5 text-[10px]"
/>
</div>
</a>
</div>
}
description="Create and configure gateway to access private network resources from Infisical"
/>
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
<div>
<div className="flex gap-2">
<Input
value={search}
onChange={(e) => setSearch(e.target.value)}
leftIcon={<FontAwesomeIcon icon={faMagnifyingGlass} />}
placeholder="Search gateway..."
className="flex-1"
/>
</div>
<TableContainer className="mt-4">
<Table>
<THead>
<Tr>
<Th className="w-1/3">Name</Th>
<Th>Identity</Th>
<Th>
Health Check
<Tooltip
asChild={false}
className="normal-case"
content="The last known healthcheck. Triggers every 1 hour."
>
<FontAwesomeIcon icon={faInfoCircle} className="ml-2" />
</Tooltip>
</Th>
<Th className="w-5" />
</Tr>
</THead>
<TBody>
{isGatewaysLoading && (
<TableSkeleton innerKey="gateway-table" columns={4} key="gateway-table" />
)}
{filteredGateway?.map((el) => (
<Tr key={el.id}>
<Td>
<div className="flex items-center gap-2">
<span>{el.name}</span>
<span className="rounded bg-mineshaft-700 px-1.5 py-0.5 text-xs text-mineshaft-400">
Gateway v{el.isV1 ? "1" : "2"}
</span>
</div>
</Td>
<Td>{el.identity.name}</Td>
<Td>
{el.heartbeat
? formatRelative(new Date(el.heartbeat), new Date())
: "-"}
</Td>
<Td className="w-5">
<Tooltip className="max-w-sm text-center" content="Options">
<DropdownMenu>
<DropdownMenuTrigger asChild>
<IconButton
ariaLabel="Options"
colorSchema="secondary"
className="w-6"
variant="plain"
>
<FontAwesomeIcon icon={faEllipsisV} />
</IconButton>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuItem
icon={<FontAwesomeIcon icon={faCopy} />}
onClick={() => navigator.clipboard.writeText(el.id)}
>
Copy ID
</DropdownMenuItem>
{el.isV1 && (
<OrgPermissionCan
I={OrgGatewayPermissionActions.EditGateways}
a={OrgPermissionSubjects.Gateway}
>
{(isAllowed: boolean) => (
<DropdownMenuItem
isDisabled={!isAllowed}
icon={<FontAwesomeIcon icon={faEdit} />}
onClick={() => handlePopUpOpen("editDetails", el)}
>
Edit Details
</DropdownMenuItem>
)}
</OrgPermissionCan>
)}
<OrgPermissionCan
I={OrgPermissionAppConnectionActions.Delete}
a={OrgPermissionSubjects.AppConnections}
>
{(isAllowed: boolean) => (
<DropdownMenuItem
isDisabled={!isAllowed}
icon={<FontAwesomeIcon icon={faTrash} />}
className="text-red"
onClick={() => handlePopUpOpen("deleteGateway", el)}
>
Delete Gateway
</DropdownMenuItem>
)}
</OrgPermissionCan>
</DropdownMenuContent>
</DropdownMenu>
</Tooltip>
</Td>
</Tr>
))}
</TBody>
</Table>
<Modal
isOpen={popUp.editDetails.isOpen}
onOpenChange={(isOpen) => handlePopUpToggle("editDetails", isOpen)}
>
<ModalContent title="Edit Gateway">
<EditGatewayDetailsModal
gatewayDetails={popUp.editDetails.data}
onClose={() => handlePopUpToggle("editDetails")}
/>
</ModalContent>
</Modal>
{!isGatewaysLoading && !filteredGateway?.length && (
<EmptyState
title={
gateways?.length
? "No Gateways match search..."
: "No Gateways have been configured"
}
icon={gateways?.length ? faSearch : faDoorClosed}
/>
)}
<DeleteActionModal
isOpen={popUp.deleteGateway.isOpen}
title={`Are you sure you want to delete gateway ${
(popUp?.deleteGateway?.data as { name: string })?.name || ""
}?`}
onChange={(isOpen) => handlePopUpToggle("deleteGateway", isOpen)}
deleteKey="confirm"
onDeleteApproved={() => handleDeleteGateway()}
/>
</TableContainer>
</div>
</div>
</div>
</div>
</div>
);
},
{ action: OrgGatewayPermissionActions.ListGateways, subject: OrgPermissionSubjects.Gateway }
);

View File

@@ -1,16 +0,0 @@
import { createFileRoute } from "@tanstack/react-router";
import { GatewayListPage } from "./GatewayListPage";
export const Route = createFileRoute(
"/_authenticate/_inject-org-details/_org-layout/organization/gateways/"
)({
component: GatewayListPage,
context: () => ({
breadcrumbs: [
{
label: "Gateways"
}
]
})
});

View File

@@ -1,214 +0,0 @@
import { useState } from "react";
import { Helmet } from "react-helmet";
import {
faArrowUpRightFromSquare,
faBookOpen,
faCopy,
faDoorClosed,
faEllipsisV,
faMagnifyingGlass,
faSearch,
faTrash
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { formatRelative } from "date-fns";
import { createNotification } from "@app/components/notifications";
import { OrgPermissionCan } from "@app/components/permissions";
import {
DeleteActionModal,
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
EmptyState,
IconButton,
Input,
PageHeader,
Table,
TableContainer,
TableSkeleton,
TBody,
Td,
Th,
THead,
Tooltip,
Tr
} from "@app/components/v2";
import {
OrgPermissionSubjects,
OrgRelayPermissionActions
} from "@app/context/OrgPermissionContext/types";
import { withPermission } from "@app/hoc";
import { usePopUp } from "@app/hooks";
import { useDeleteRelayById, useGetRelays } from "@app/hooks/api/relays";
export const RelayListPage = withPermission(
() => {
const [search, setSearch] = useState("");
const { data: relays, isPending: isRelaysLoading } = useGetRelays();
const { popUp, handlePopUpOpen, handlePopUpToggle } = usePopUp(["deleteRelay"] as const);
const deleteRelayById = useDeleteRelayById();
const handleDeleteRelay = async () => {
const data = popUp.deleteRelay.data as { id: string };
await deleteRelayById.mutateAsync(data.id);
handlePopUpToggle("deleteRelay");
createNotification({
type: "success",
text: "Successfully deleted relay"
});
};
const filteredRelays = relays?.filter((el) =>
el.name.toLowerCase().includes(search.toLowerCase())
);
return (
<div className="bg-bunker-800">
<Helmet>
<title>Infisical | Relays</title>
<meta property="og:image" content="/images/message.png" />
</Helmet>
<div className="flex w-full justify-center bg-bunker-800 text-white">
<div className="w-full max-w-7xl">
<PageHeader
className="w-full"
title={
<div className="flex w-full items-center">
<span>Relays</span>
<a
className="-mt-1.5"
href="https://infisical.com/docs/documentation/platform/gateways/relay-deployment"
target="_blank"
rel="noopener noreferrer"
>
<div className="ml-2 inline-block rounded-md bg-yellow/20 px-1.5 text-sm font-normal text-yellow opacity-80 hover:opacity-100">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
<span>Docs</span>
<FontAwesomeIcon
icon={faArrowUpRightFromSquare}
className="mb-[0.07rem] ml-1.5 text-[10px]"
/>
</div>
</a>
</div>
}
description="Create and configure relays to securely access private network resources from Infisical"
/>
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
<div>
<div className="flex gap-2">
<Input
value={search}
onChange={(e) => setSearch(e.target.value)}
leftIcon={<FontAwesomeIcon icon={faMagnifyingGlass} />}
placeholder="Search relay..."
className="flex-1"
/>
</div>
<TableContainer className="mt-4">
<Table>
<THead>
<Tr>
<Th className="w-1/3">Name</Th>
<Th>Host</Th>
<Th>Created</Th>
<Th className="w-5" />
</Tr>
</THead>
<TBody>
{isRelaysLoading && (
<TableSkeleton innerKey="relay-table" columns={4} key="relay-table" />
)}
{filteredRelays?.map((el) => (
<Tr key={el.id}>
<Td>
<div className="flex items-center gap-2">
<span>{el.name}</span>
{!el.orgId && (
<Tooltip content="This is a managed relay provided by Infisical">
<span className="rounded bg-mineshaft-700 px-1.5 py-0.5 text-xs text-mineshaft-400">
Managed
</span>
</Tooltip>
)}
</div>
</Td>
<Td>{el.host}</Td>
<Td>{formatRelative(new Date(el.createdAt), new Date())}</Td>
<Td className="w-5">
<Tooltip className="max-w-sm text-center" content="Options">
<DropdownMenu>
<DropdownMenuTrigger asChild>
<IconButton
ariaLabel="Options"
colorSchema="secondary"
className="w-6"
variant="plain"
>
<FontAwesomeIcon icon={faEllipsisV} />
</IconButton>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuItem
icon={<FontAwesomeIcon icon={faCopy} />}
onClick={() => navigator.clipboard.writeText(el.id)}
>
Copy ID
</DropdownMenuItem>
<OrgPermissionCan
I={OrgRelayPermissionActions.DeleteRelays}
a={OrgPermissionSubjects.Relay}
>
{(isAllowed: boolean) => (
<DropdownMenuItem
isDisabled={!isAllowed || !el.orgId}
icon={<FontAwesomeIcon icon={faTrash} />}
className="text-red"
onClick={() => handlePopUpOpen("deleteRelay", el)}
>
Delete Relay
</DropdownMenuItem>
)}
</OrgPermissionCan>
</DropdownMenuContent>
</DropdownMenu>
</Tooltip>
</Td>
</Tr>
))}
</TBody>
</Table>
{!isRelaysLoading && !filteredRelays?.length && (
<EmptyState
title={
relays?.length
? "No Relays match search..."
: "No Relays have been configured"
}
icon={relays?.length ? faSearch : faDoorClosed}
/>
)}
<DeleteActionModal
isOpen={popUp.deleteRelay.isOpen}
title={`Are you sure you want to delete relay ${
(popUp?.deleteRelay?.data as { name: string })?.name || ""
}?`}
onChange={(isOpen) => handlePopUpToggle("deleteRelay", isOpen)}
deleteKey="confirm"
onDeleteApproved={() => handleDeleteRelay()}
/>
</TableContainer>
</div>
</div>
</div>
</div>
</div>
);
},
{ action: OrgRelayPermissionActions.ListRelays, subject: OrgPermissionSubjects.Relay }
);

View File

@@ -1,16 +0,0 @@
import { createFileRoute } from "@tanstack/react-router";
import { RelayListPage } from "./RelayListPage";
export const Route = createFileRoute(
"/_authenticate/_inject-org-details/_org-layout/organization/relays/"
)({
component: RelayListPage,
context: () => ({
breadcrumbs: [
{
label: "Relays"
}
]
})
});

View File

@@ -0,0 +1,25 @@
import { Helmet } from "react-helmet";
import { PageHeader } from "@app/components/v2";
import { NetworkingTabGroup } from "./components/NetworkingTabGroup/NetworkingTabGroup";
export const NetworkingPage = () => {
return (
<>
<Helmet>
<title>Infisical | Networking</title>
<meta property="og:image" content="/images/message.png" />
</Helmet>
<div className="flex w-full justify-center bg-bunker-800 text-white">
<div className="w-full max-w-7xl">
<PageHeader
title="Networking"
description="Manage gateways and relays to securely access private network resources from Infisical"
/>
<NetworkingTabGroup />
</div>
</div>
</>
);
};

View File

@@ -0,0 +1,251 @@
import { useState } from "react";
import {
faArrowUpRightFromSquare,
faBookOpen,
faCopy,
faDoorClosed,
faEdit,
faEllipsisV,
faInfoCircle,
faMagnifyingGlass,
faSearch,
faTrash
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { useQuery } from "@tanstack/react-query";
import { formatRelative } from "date-fns";
import { createNotification } from "@app/components/notifications";
import { OrgPermissionCan } from "@app/components/permissions";
import {
DeleteActionModal,
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
EmptyState,
IconButton,
Input,
Modal,
ModalContent,
Table,
TableContainer,
TableSkeleton,
TBody,
Td,
Th,
THead,
Tooltip,
Tr
} from "@app/components/v2";
import {
OrgGatewayPermissionActions,
OrgPermissionAppConnectionActions,
OrgPermissionSubjects
} from "@app/context/OrgPermissionContext/types";
import { withPermission } from "@app/hoc";
import { usePopUp } from "@app/hooks";
import { gatewaysQueryKeys, useDeleteGatewayById } from "@app/hooks/api/gateways";
import { useDeleteGatewayV2ById } from "@app/hooks/api/gateways-v2";
import { EditGatewayDetailsModal } from "./components/EditGatewayDetailsModal";
export const GatewayTab = withPermission(
() => {
const [search, setSearch] = useState("");
const { data: gateways, isPending: isGatewaysLoading } = useQuery(gatewaysQueryKeys.list());
const { popUp, handlePopUpOpen, handlePopUpToggle } = usePopUp([
"deleteGateway",
"editDetails"
] as const);
const deleteGatewayById = useDeleteGatewayById();
const deleteGatewayV2ById = useDeleteGatewayV2ById();
const handleDeleteGateway = async () => {
const data = popUp.deleteGateway.data as { id: string; isV1: boolean };
if (data.isV1) {
await deleteGatewayById.mutateAsync(data.id);
} else {
await deleteGatewayV2ById.mutateAsync(data.id);
}
handlePopUpToggle("deleteGateway");
createNotification({
type: "success",
text: "Successfully deleted gateway"
});
};
const filteredGateway = gateways?.filter((el) =>
el.name.toLowerCase().includes(search.toLowerCase())
);
return (
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
<div className="mb-4 flex items-center justify-between">
<div className="flex items-center gap-2">
<h3 className="text-lg font-semibold text-mineshaft-100">Gateways</h3>
<a
href="https://infisical.com/docs/documentation/platform/gateways/overview"
target="_blank"
rel="noopener noreferrer"
>
<div className="inline-block rounded-md bg-yellow/20 px-1.5 py-0.5 text-sm font-normal text-yellow opacity-80 hover:opacity-100">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
<span>Docs</span>
<FontAwesomeIcon
icon={faArrowUpRightFromSquare}
className="mb-[0.07rem] ml-1.5 text-[10px]"
/>
</div>
</a>
</div>
</div>
<p className="mb-4 text-sm text-mineshaft-400">
Create and configure gateway to access private network resources from Infisical
</p>
<div>
<div className="flex gap-2">
<Input
value={search}
onChange={(e) => setSearch(e.target.value)}
leftIcon={<FontAwesomeIcon icon={faMagnifyingGlass} />}
placeholder="Search gateway..."
className="flex-1"
/>
</div>
<TableContainer className="mt-4">
<Table>
<THead>
<Tr>
<Th className="w-1/3">Name</Th>
<Th>Identity</Th>
<Th>
Health Check
<Tooltip
asChild={false}
className="normal-case"
content="The last known healthcheck. Triggers every 1 hour."
>
<FontAwesomeIcon icon={faInfoCircle} className="ml-2" />
</Tooltip>
</Th>
<Th className="w-5" />
</Tr>
</THead>
<TBody>
{isGatewaysLoading && (
<TableSkeleton innerKey="gateway-table" columns={4} key="gateway-table" />
)}
{filteredGateway?.map((el) => (
<Tr key={el.id}>
<Td>
<div className="flex items-center gap-2">
<span>{el.name}</span>
<span className="rounded bg-mineshaft-700 px-1.5 py-0.5 text-xs text-mineshaft-400">
Gateway v{el.isV1 ? "1" : "2"}
</span>
</div>
</Td>
<Td>{el.identity.name}</Td>
<Td>
{el.heartbeat ? formatRelative(new Date(el.heartbeat), new Date()) : "-"}
</Td>
<Td className="w-5">
<Tooltip className="max-w-sm text-center" content="Options">
<DropdownMenu>
<DropdownMenuTrigger asChild>
<IconButton
ariaLabel="Options"
colorSchema="secondary"
className="w-6"
variant="plain"
>
<FontAwesomeIcon icon={faEllipsisV} />
</IconButton>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuItem
icon={<FontAwesomeIcon icon={faCopy} />}
onClick={() => navigator.clipboard.writeText(el.id)}
>
Copy ID
</DropdownMenuItem>
{el.isV1 && (
<OrgPermissionCan
I={OrgGatewayPermissionActions.EditGateways}
a={OrgPermissionSubjects.Gateway}
>
{(isAllowed: boolean) => (
<DropdownMenuItem
isDisabled={!isAllowed}
icon={<FontAwesomeIcon icon={faEdit} />}
onClick={() => handlePopUpOpen("editDetails", el)}
>
Edit Details
</DropdownMenuItem>
)}
</OrgPermissionCan>
)}
<OrgPermissionCan
I={OrgPermissionAppConnectionActions.Delete}
a={OrgPermissionSubjects.AppConnections}
>
{(isAllowed: boolean) => (
<DropdownMenuItem
isDisabled={!isAllowed}
icon={<FontAwesomeIcon icon={faTrash} />}
className="text-red"
onClick={() => handlePopUpOpen("deleteGateway", el)}
>
Delete Gateway
</DropdownMenuItem>
)}
</OrgPermissionCan>
</DropdownMenuContent>
</DropdownMenu>
</Tooltip>
</Td>
</Tr>
))}
</TBody>
</Table>
<Modal
isOpen={popUp.editDetails.isOpen}
onOpenChange={(isOpen) => handlePopUpToggle("editDetails", isOpen)}
>
<ModalContent title="Edit Gateway">
<EditGatewayDetailsModal
gatewayDetails={popUp.editDetails.data}
onClose={() => handlePopUpToggle("editDetails")}
/>
</ModalContent>
</Modal>
{!isGatewaysLoading && !filteredGateway?.length && (
<EmptyState
title={
gateways?.length
? "No Gateways match search..."
: "No Gateways have been configured"
}
icon={gateways?.length ? faSearch : faDoorClosed}
/>
)}
<DeleteActionModal
isOpen={popUp.deleteGateway.isOpen}
title={`Are you sure you want to delete gateway ${
(popUp?.deleteGateway?.data as { name: string })?.name || ""
}?`}
onChange={(isOpen) => handlePopUpToggle("deleteGateway", isOpen)}
deleteKey="confirm"
onDeleteApproved={() => handleDeleteGateway()}
/>
</TableContainer>
</div>
</div>
);
},
{ action: OrgGatewayPermissionActions.ListGateways, subject: OrgPermissionSubjects.Gateway }
);

View File

@@ -0,0 +1 @@
export { GatewayTab } from "./GatewayTab";

View File

@@ -0,0 +1,37 @@
import { useState } from "react";
import { useSearch } from "@tanstack/react-router";
import { Tab, TabList, TabPanel, Tabs } from "@app/components/v2";
import { GatewayTab } from "../GatewayTab/GatewayTab";
import { RelayTab } from "../RelayTab/RelayTab";
export const NetworkingTabGroup = () => {
const search = useSearch({
from: "/_authenticate/_inject-org-details/_org-layout/organization/networking/"
});
const tabs = [
{ name: "Gateways", key: "gateways", component: GatewayTab },
{ name: "Relays", key: "relays", component: RelayTab }
];
const [selectedTab, setSelectedTab] = useState(search.selectedTab || tabs[0].key);
return (
<Tabs value={selectedTab} onValueChange={setSelectedTab}>
<TabList>
{tabs.map((tab) => (
<Tab value={tab.key} key={tab.key}>
{tab.name}
</Tab>
))}
</TabList>
{tabs.map(({ key, component: Component }) => (
<TabPanel value={key} key={`tab-panel-${key}`}>
<Component />
</TabPanel>
))}
</Tabs>
);
};

View File

@@ -0,0 +1 @@
export { NetworkingTabGroup } from "./NetworkingTabGroup";

View File

@@ -0,0 +1,198 @@
import { useState } from "react";
import {
faArrowUpRightFromSquare,
faBookOpen,
faCopy,
faDoorClosed,
faEllipsisV,
faMagnifyingGlass,
faSearch,
faTrash
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { formatRelative } from "date-fns";
import { createNotification } from "@app/components/notifications";
import { OrgPermissionCan } from "@app/components/permissions";
import {
DeleteActionModal,
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
EmptyState,
IconButton,
Input,
Table,
TableContainer,
TableSkeleton,
TBody,
Td,
Th,
THead,
Tooltip,
Tr
} from "@app/components/v2";
import {
OrgPermissionSubjects,
OrgRelayPermissionActions
} from "@app/context/OrgPermissionContext/types";
import { withPermission } from "@app/hoc";
import { usePopUp } from "@app/hooks";
import { useDeleteRelayById, useGetRelays } from "@app/hooks/api/relays";
export const RelayTab = withPermission(
() => {
const [search, setSearch] = useState("");
const { data: relays, isPending: isRelaysLoading } = useGetRelays();
const { popUp, handlePopUpOpen, handlePopUpToggle } = usePopUp(["deleteRelay"] as const);
const deleteRelayById = useDeleteRelayById();
const handleDeleteRelay = async () => {
const data = popUp.deleteRelay.data as { id: string };
await deleteRelayById.mutateAsync(data.id);
handlePopUpToggle("deleteRelay");
createNotification({
type: "success",
text: "Successfully deleted relay"
});
};
const filteredRelays = relays?.filter((el) =>
el.name.toLowerCase().includes(search.toLowerCase())
);
return (
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
<div className="mb-4 flex items-center justify-between">
<div className="flex items-center gap-2">
<h3 className="text-lg font-semibold text-mineshaft-100">Relays</h3>
<a
href="https://infisical.com/docs/documentation/platform/gateways/relay-deployment"
target="_blank"
rel="noopener noreferrer"
>
<div className="inline-block rounded-md bg-yellow/20 px-1.5 py-0.5 text-sm font-normal text-yellow opacity-80 hover:opacity-100">
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
<span>Docs</span>
<FontAwesomeIcon
icon={faArrowUpRightFromSquare}
className="mb-[0.07rem] ml-1.5 text-[10px]"
/>
</div>
</a>
</div>
</div>
<p className="mb-4 text-sm text-mineshaft-400">
Create and configure relays to securely access private network resources from Infisical
</p>
<div>
<div className="flex gap-2">
<Input
value={search}
onChange={(e) => setSearch(e.target.value)}
leftIcon={<FontAwesomeIcon icon={faMagnifyingGlass} />}
placeholder="Search relay..."
className="flex-1"
/>
</div>
<TableContainer className="mt-4">
<Table>
<THead>
<Tr>
<Th className="w-1/3">Name</Th>
<Th>Host</Th>
<Th>Created</Th>
<Th className="w-5" />
</Tr>
</THead>
<TBody>
{isRelaysLoading && (
<TableSkeleton innerKey="relay-table" columns={4} key="relay-table" />
)}
{filteredRelays?.map((el) => (
<Tr key={el.id}>
<Td>
<div className="flex items-center gap-2">
<span>{el.name}</span>
{!el.orgId && (
<Tooltip content="This is a managed relay provided by Infisical">
<span className="rounded bg-mineshaft-700 px-1.5 py-0.5 text-xs text-mineshaft-400">
Managed
</span>
</Tooltip>
)}
</div>
</Td>
<Td>{el.host}</Td>
<Td>{formatRelative(new Date(el.createdAt), new Date())}</Td>
<Td className="w-5">
<Tooltip className="max-w-sm text-center" content="Options">
<DropdownMenu>
<DropdownMenuTrigger asChild>
<IconButton
ariaLabel="Options"
colorSchema="secondary"
className="w-6"
variant="plain"
>
<FontAwesomeIcon icon={faEllipsisV} />
</IconButton>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuItem
icon={<FontAwesomeIcon icon={faCopy} />}
onClick={() => navigator.clipboard.writeText(el.id)}
>
Copy ID
</DropdownMenuItem>
<OrgPermissionCan
I={OrgRelayPermissionActions.DeleteRelays}
a={OrgPermissionSubjects.Relay}
>
{(isAllowed: boolean) => (
<DropdownMenuItem
isDisabled={!isAllowed || !el.orgId}
icon={<FontAwesomeIcon icon={faTrash} />}
className="text-red"
onClick={() => handlePopUpOpen("deleteRelay", el)}
>
Delete Relay
</DropdownMenuItem>
)}
</OrgPermissionCan>
</DropdownMenuContent>
</DropdownMenu>
</Tooltip>
</Td>
</Tr>
))}
</TBody>
</Table>
{!isRelaysLoading && !filteredRelays?.length && (
<EmptyState
title={
relays?.length ? "No Relays match search..." : "No Relays have been configured"
}
icon={relays?.length ? faSearch : faDoorClosed}
/>
)}
<DeleteActionModal
isOpen={popUp.deleteRelay.isOpen}
title={`Are you sure you want to delete relay ${
(popUp?.deleteRelay?.data as { name: string })?.name || ""
}?`}
onChange={(isOpen) => handlePopUpToggle("deleteRelay", isOpen)}
deleteKey="confirm"
onDeleteApproved={() => handleDeleteRelay()}
/>
</TableContainer>
</div>
</div>
);
},
{ action: OrgRelayPermissionActions.ListRelays, subject: OrgPermissionSubjects.Relay }
);

View File

@@ -0,0 +1 @@
export { RelayTab } from "./RelayTab";

View File

@@ -0,0 +1,3 @@
export { GatewayTab } from "./GatewayTab/GatewayTab";
export { NetworkingTabGroup } from "./NetworkingTabGroup/NetworkingTabGroup";
export { RelayTab } from "./RelayTab/RelayTab";

View File

@@ -0,0 +1,26 @@
import { createFileRoute, stripSearchParams } from "@tanstack/react-router";
import { zodValidator } from "@tanstack/zod-adapter";
import { z } from "zod";
import { NetworkingPage } from "./NetworkingPage";
const NetworkingPageQueryParams = z.object({
selectedTab: z.string().catch("")
});
export const Route = createFileRoute(
"/_authenticate/_inject-org-details/_org-layout/organization/networking/"
)({
component: NetworkingPage,
validateSearch: zodValidator(NetworkingPageQueryParams),
search: {
middlewares: [stripSearchParams({ selectedTab: "" })]
},
context: () => ({
breadcrumbs: [
{
label: "Networking"
}
]
})
});

View File

@@ -62,8 +62,7 @@ import { Route as organizationIdentityDetailsByIDPageRouteImport } from './pages
import { Route as organizationGroupDetailsByIDPageRouteImport } from './pages/organization/GroupDetailsByIDPage/route'
import { Route as organizationSettingsPageRouteImport } from './pages/organization/SettingsPage/route'
import { Route as organizationSecretSharingPageRouteImport } from './pages/organization/SecretSharingPage/route'
import { Route as organizationGatewaysRelayRelayListPageRouteImport } from './pages/organization/Gateways/Relay/RelayListPage/route'
import { Route as organizationGatewaysGatewayListPageRouteImport } from './pages/organization/Gateways/GatewayListPage/route'
import { Route as organizationNetworkingPageRouteImport } from './pages/organization/NetworkingPage/route'
import { Route as organizationAppConnectionsAppConnectionsPageRouteImport } from './pages/organization/AppConnections/AppConnectionsPage/route'
import { Route as sshLayoutImport } from './pages/ssh/layout'
import { Route as secretScanningLayoutImport } from './pages/secret-scanning/layout'
@@ -256,13 +255,9 @@ const AuthenticateInjectOrgDetailsOrgLayoutOrganizationSecretSharingImport =
createFileRoute(
'/_authenticate/_inject-org-details/_org-layout/organization/secret-sharing',
)()
const AuthenticateInjectOrgDetailsOrgLayoutOrganizationRelaysImport =
const AuthenticateInjectOrgDetailsOrgLayoutOrganizationNetworkingImport =
createFileRoute(
'/_authenticate/_inject-org-details/_org-layout/organization/relays',
)()
const AuthenticateInjectOrgDetailsOrgLayoutOrganizationGatewaysImport =
createFileRoute(
'/_authenticate/_inject-org-details/_org-layout/organization/gateways',
'/_authenticate/_inject-org-details/_org-layout/organization/networking',
)()
const AuthenticateInjectOrgDetailsOrgLayoutOrganizationAppConnectionsImport =
createFileRoute(
@@ -564,18 +559,10 @@ const AuthenticateInjectOrgDetailsOrgLayoutOrganizationSecretSharingRoute =
AuthenticateInjectOrgDetailsOrgLayoutOrganizationRoute,
} as any)
const AuthenticateInjectOrgDetailsOrgLayoutOrganizationRelaysRoute =
AuthenticateInjectOrgDetailsOrgLayoutOrganizationRelaysImport.update({
id: '/relays',
path: '/relays',
getParentRoute: () =>
AuthenticateInjectOrgDetailsOrgLayoutOrganizationRoute,
} as any)
const AuthenticateInjectOrgDetailsOrgLayoutOrganizationGatewaysRoute =
AuthenticateInjectOrgDetailsOrgLayoutOrganizationGatewaysImport.update({
id: '/gateways',
path: '/gateways',
const AuthenticateInjectOrgDetailsOrgLayoutOrganizationNetworkingRoute =
AuthenticateInjectOrgDetailsOrgLayoutOrganizationNetworkingImport.update({
id: '/networking',
path: '/networking',
getParentRoute: () =>
AuthenticateInjectOrgDetailsOrgLayoutOrganizationRoute,
} as any)
@@ -778,20 +765,12 @@ const organizationSecretSharingPageRouteRoute =
AuthenticateInjectOrgDetailsOrgLayoutOrganizationSecretSharingRoute,
} as any)
const organizationGatewaysRelayRelayListPageRouteRoute =
organizationGatewaysRelayRelayListPageRouteImport.update({
const organizationNetworkingPageRouteRoute =
organizationNetworkingPageRouteImport.update({
id: '/',
path: '/',
getParentRoute: () =>
AuthenticateInjectOrgDetailsOrgLayoutOrganizationRelaysRoute,
} as any)
const organizationGatewaysGatewayListPageRouteRoute =
organizationGatewaysGatewayListPageRouteImport.update({
id: '/',
path: '/',
getParentRoute: () =>
AuthenticateInjectOrgDetailsOrgLayoutOrganizationGatewaysRoute,
AuthenticateInjectOrgDetailsOrgLayoutOrganizationNetworkingRoute,
} as any)
const organizationAppConnectionsAppConnectionsPageRouteRoute =
@@ -2390,18 +2369,11 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationAppConnectionsImport
parentRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationImport
}
'/_authenticate/_inject-org-details/_org-layout/organization/gateways': {
id: '/_authenticate/_inject-org-details/_org-layout/organization/gateways'
path: '/gateways'
fullPath: '/organization/gateways'
preLoaderRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationGatewaysImport
parentRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationImport
}
'/_authenticate/_inject-org-details/_org-layout/organization/relays': {
id: '/_authenticate/_inject-org-details/_org-layout/organization/relays'
path: '/relays'
fullPath: '/organization/relays'
preLoaderRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationRelaysImport
'/_authenticate/_inject-org-details/_org-layout/organization/networking': {
id: '/_authenticate/_inject-org-details/_org-layout/organization/networking'
path: '/networking'
fullPath: '/organization/networking'
preLoaderRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationNetworkingImport
parentRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationImport
}
'/_authenticate/_inject-org-details/_org-layout/organization/secret-sharing': {
@@ -2432,19 +2404,12 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof organizationAppConnectionsAppConnectionsPageRouteImport
parentRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationAppConnectionsImport
}
'/_authenticate/_inject-org-details/_org-layout/organization/gateways/': {
id: '/_authenticate/_inject-org-details/_org-layout/organization/gateways/'
'/_authenticate/_inject-org-details/_org-layout/organization/networking/': {
id: '/_authenticate/_inject-org-details/_org-layout/organization/networking/'
path: '/'
fullPath: '/organization/gateways/'
preLoaderRoute: typeof organizationGatewaysGatewayListPageRouteImport
parentRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationGatewaysImport
}
'/_authenticate/_inject-org-details/_org-layout/organization/relays/': {
id: '/_authenticate/_inject-org-details/_org-layout/organization/relays/'
path: '/'
fullPath: '/organization/relays/'
preLoaderRoute: typeof organizationGatewaysRelayRelayListPageRouteImport
parentRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationRelaysImport
fullPath: '/organization/networking/'
preLoaderRoute: typeof organizationNetworkingPageRouteImport
parentRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationNetworkingImport
}
'/_authenticate/_inject-org-details/_org-layout/organization/secret-sharing/': {
id: '/_authenticate/_inject-org-details/_org-layout/organization/secret-sharing/'
@@ -3754,34 +3719,18 @@ const AuthenticateInjectOrgDetailsOrgLayoutOrganizationAppConnectionsRouteWithCh
AuthenticateInjectOrgDetailsOrgLayoutOrganizationAppConnectionsRouteChildren,
)
interface AuthenticateInjectOrgDetailsOrgLayoutOrganizationGatewaysRouteChildren {
organizationGatewaysGatewayListPageRouteRoute: typeof organizationGatewaysGatewayListPageRouteRoute
interface AuthenticateInjectOrgDetailsOrgLayoutOrganizationNetworkingRouteChildren {
organizationNetworkingPageRouteRoute: typeof organizationNetworkingPageRouteRoute
}
const AuthenticateInjectOrgDetailsOrgLayoutOrganizationGatewaysRouteChildren: AuthenticateInjectOrgDetailsOrgLayoutOrganizationGatewaysRouteChildren =
const AuthenticateInjectOrgDetailsOrgLayoutOrganizationNetworkingRouteChildren: AuthenticateInjectOrgDetailsOrgLayoutOrganizationNetworkingRouteChildren =
{
organizationGatewaysGatewayListPageRouteRoute:
organizationGatewaysGatewayListPageRouteRoute,
organizationNetworkingPageRouteRoute: organizationNetworkingPageRouteRoute,
}
const AuthenticateInjectOrgDetailsOrgLayoutOrganizationGatewaysRouteWithChildren =
AuthenticateInjectOrgDetailsOrgLayoutOrganizationGatewaysRoute._addFileChildren(
AuthenticateInjectOrgDetailsOrgLayoutOrganizationGatewaysRouteChildren,
)
interface AuthenticateInjectOrgDetailsOrgLayoutOrganizationRelaysRouteChildren {
organizationGatewaysRelayRelayListPageRouteRoute: typeof organizationGatewaysRelayRelayListPageRouteRoute
}
const AuthenticateInjectOrgDetailsOrgLayoutOrganizationRelaysRouteChildren: AuthenticateInjectOrgDetailsOrgLayoutOrganizationRelaysRouteChildren =
{
organizationGatewaysRelayRelayListPageRouteRoute:
organizationGatewaysRelayRelayListPageRouteRoute,
}
const AuthenticateInjectOrgDetailsOrgLayoutOrganizationRelaysRouteWithChildren =
AuthenticateInjectOrgDetailsOrgLayoutOrganizationRelaysRoute._addFileChildren(
AuthenticateInjectOrgDetailsOrgLayoutOrganizationRelaysRouteChildren,
const AuthenticateInjectOrgDetailsOrgLayoutOrganizationNetworkingRouteWithChildren =
AuthenticateInjectOrgDetailsOrgLayoutOrganizationNetworkingRoute._addFileChildren(
AuthenticateInjectOrgDetailsOrgLayoutOrganizationNetworkingRouteChildren,
)
interface AuthenticateInjectOrgDetailsOrgLayoutOrganizationSecretSharingRouteChildren {
@@ -3825,8 +3774,7 @@ interface AuthenticateInjectOrgDetailsOrgLayoutOrganizationRouteChildren {
organizationBillingPageRouteRoute: typeof organizationBillingPageRouteRoute
organizationProjectsPageRouteRoute: typeof organizationProjectsPageRouteRoute
AuthenticateInjectOrgDetailsOrgLayoutOrganizationAppConnectionsRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationAppConnectionsRouteWithChildren
AuthenticateInjectOrgDetailsOrgLayoutOrganizationGatewaysRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationGatewaysRouteWithChildren
AuthenticateInjectOrgDetailsOrgLayoutOrganizationRelaysRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationRelaysRouteWithChildren
AuthenticateInjectOrgDetailsOrgLayoutOrganizationNetworkingRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationNetworkingRouteWithChildren
AuthenticateInjectOrgDetailsOrgLayoutOrganizationSecretSharingRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationSecretSharingRouteWithChildren
AuthenticateInjectOrgDetailsOrgLayoutOrganizationSettingsRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationSettingsRouteWithChildren
organizationGroupDetailsByIDPageRouteRoute: typeof organizationGroupDetailsByIDPageRouteRoute
@@ -3844,10 +3792,8 @@ const AuthenticateInjectOrgDetailsOrgLayoutOrganizationRouteChildren: Authentica
organizationProjectsPageRouteRoute: organizationProjectsPageRouteRoute,
AuthenticateInjectOrgDetailsOrgLayoutOrganizationAppConnectionsRoute:
AuthenticateInjectOrgDetailsOrgLayoutOrganizationAppConnectionsRouteWithChildren,
AuthenticateInjectOrgDetailsOrgLayoutOrganizationGatewaysRoute:
AuthenticateInjectOrgDetailsOrgLayoutOrganizationGatewaysRouteWithChildren,
AuthenticateInjectOrgDetailsOrgLayoutOrganizationRelaysRoute:
AuthenticateInjectOrgDetailsOrgLayoutOrganizationRelaysRouteWithChildren,
AuthenticateInjectOrgDetailsOrgLayoutOrganizationNetworkingRoute:
AuthenticateInjectOrgDetailsOrgLayoutOrganizationNetworkingRouteWithChildren,
AuthenticateInjectOrgDetailsOrgLayoutOrganizationSecretSharingRoute:
AuthenticateInjectOrgDetailsOrgLayoutOrganizationSecretSharingRouteWithChildren,
AuthenticateInjectOrgDetailsOrgLayoutOrganizationSettingsRoute:
@@ -4746,14 +4692,12 @@ export interface FileRoutesByFullPath {
'/admin/environment': typeof adminEnvironmentPageRouteRoute
'/admin/integrations': typeof adminIntegrationsPageRouteRoute
'/organization/app-connections': typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationAppConnectionsRouteWithChildren
'/organization/gateways': typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationGatewaysRouteWithChildren
'/organization/relays': typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationRelaysRouteWithChildren
'/organization/networking': typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationNetworkingRouteWithChildren
'/organization/secret-sharing': typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationSecretSharingRouteWithChildren
'/organization/settings': typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationSettingsRouteWithChildren
'/secret-manager/$projectId': typeof AuthenticateInjectOrgDetailsOrgLayoutSecretManagerProjectIdRouteWithChildren
'/organization/app-connections/': typeof organizationAppConnectionsAppConnectionsPageRouteRoute
'/organization/gateways/': typeof organizationGatewaysGatewayListPageRouteRoute
'/organization/relays/': typeof organizationGatewaysRelayRelayListPageRouteRoute
'/organization/networking/': typeof organizationNetworkingPageRouteRoute
'/organization/secret-sharing/': typeof organizationSecretSharingPageRouteRoute
'/organization/settings/': typeof organizationSettingsPageRouteRoute
'/organization/groups/$groupId': typeof organizationGroupDetailsByIDPageRouteRoute
@@ -4969,8 +4913,7 @@ export interface FileRoutesByTo {
'/admin/integrations': typeof adminIntegrationsPageRouteRoute
'/secret-manager/$projectId': typeof AuthenticateInjectOrgDetailsOrgLayoutSecretManagerProjectIdRouteWithChildren
'/organization/app-connections': typeof organizationAppConnectionsAppConnectionsPageRouteRoute
'/organization/gateways': typeof organizationGatewaysGatewayListPageRouteRoute
'/organization/relays': typeof organizationGatewaysRelayRelayListPageRouteRoute
'/organization/networking': typeof organizationNetworkingPageRouteRoute
'/organization/secret-sharing': typeof organizationSecretSharingPageRouteRoute
'/organization/settings': typeof organizationSettingsPageRouteRoute
'/organization/groups/$groupId': typeof organizationGroupDetailsByIDPageRouteRoute
@@ -5189,14 +5132,12 @@ export interface FileRoutesById {
'/_authenticate/_inject-org-details/admin/_admin-layout/environment': typeof adminEnvironmentPageRouteRoute
'/_authenticate/_inject-org-details/admin/_admin-layout/integrations': typeof adminIntegrationsPageRouteRoute
'/_authenticate/_inject-org-details/_org-layout/organization/app-connections': typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationAppConnectionsRouteWithChildren
'/_authenticate/_inject-org-details/_org-layout/organization/gateways': typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationGatewaysRouteWithChildren
'/_authenticate/_inject-org-details/_org-layout/organization/relays': typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationRelaysRouteWithChildren
'/_authenticate/_inject-org-details/_org-layout/organization/networking': typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationNetworkingRouteWithChildren
'/_authenticate/_inject-org-details/_org-layout/organization/secret-sharing': typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationSecretSharingRouteWithChildren
'/_authenticate/_inject-org-details/_org-layout/organization/settings': typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationSettingsRouteWithChildren
'/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId': typeof AuthenticateInjectOrgDetailsOrgLayoutSecretManagerProjectIdRouteWithChildren
'/_authenticate/_inject-org-details/_org-layout/organization/app-connections/': typeof organizationAppConnectionsAppConnectionsPageRouteRoute
'/_authenticate/_inject-org-details/_org-layout/organization/gateways/': typeof organizationGatewaysGatewayListPageRouteRoute
'/_authenticate/_inject-org-details/_org-layout/organization/relays/': typeof organizationGatewaysRelayRelayListPageRouteRoute
'/_authenticate/_inject-org-details/_org-layout/organization/networking/': typeof organizationNetworkingPageRouteRoute
'/_authenticate/_inject-org-details/_org-layout/organization/secret-sharing/': typeof organizationSecretSharingPageRouteRoute
'/_authenticate/_inject-org-details/_org-layout/organization/settings/': typeof organizationSettingsPageRouteRoute
'/_authenticate/_inject-org-details/_org-layout/organization/groups/$groupId': typeof organizationGroupDetailsByIDPageRouteRoute
@@ -5422,14 +5363,12 @@ export interface FileRouteTypes {
| '/admin/environment'
| '/admin/integrations'
| '/organization/app-connections'
| '/organization/gateways'
| '/organization/relays'
| '/organization/networking'
| '/organization/secret-sharing'
| '/organization/settings'
| '/secret-manager/$projectId'
| '/organization/app-connections/'
| '/organization/gateways/'
| '/organization/relays/'
| '/organization/networking/'
| '/organization/secret-sharing/'
| '/organization/settings/'
| '/organization/groups/$groupId'
@@ -5644,8 +5583,7 @@ export interface FileRouteTypes {
| '/admin/integrations'
| '/secret-manager/$projectId'
| '/organization/app-connections'
| '/organization/gateways'
| '/organization/relays'
| '/organization/networking'
| '/organization/secret-sharing'
| '/organization/settings'
| '/organization/groups/$groupId'
@@ -5862,14 +5800,12 @@ export interface FileRouteTypes {
| '/_authenticate/_inject-org-details/admin/_admin-layout/environment'
| '/_authenticate/_inject-org-details/admin/_admin-layout/integrations'
| '/_authenticate/_inject-org-details/_org-layout/organization/app-connections'
| '/_authenticate/_inject-org-details/_org-layout/organization/gateways'
| '/_authenticate/_inject-org-details/_org-layout/organization/relays'
| '/_authenticate/_inject-org-details/_org-layout/organization/networking'
| '/_authenticate/_inject-org-details/_org-layout/organization/secret-sharing'
| '/_authenticate/_inject-org-details/_org-layout/organization/settings'
| '/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId'
| '/_authenticate/_inject-org-details/_org-layout/organization/app-connections/'
| '/_authenticate/_inject-org-details/_org-layout/organization/gateways/'
| '/_authenticate/_inject-org-details/_org-layout/organization/relays/'
| '/_authenticate/_inject-org-details/_org-layout/organization/networking/'
| '/_authenticate/_inject-org-details/_org-layout/organization/secret-sharing/'
| '/_authenticate/_inject-org-details/_org-layout/organization/settings/'
| '/_authenticate/_inject-org-details/_org-layout/organization/groups/$groupId'
@@ -6290,8 +6226,7 @@ export const routeTree = rootRoute
"/_authenticate/_inject-org-details/_org-layout/organization/billing",
"/_authenticate/_inject-org-details/_org-layout/organization/projects",
"/_authenticate/_inject-org-details/_org-layout/organization/app-connections",
"/_authenticate/_inject-org-details/_org-layout/organization/gateways",
"/_authenticate/_inject-org-details/_org-layout/organization/relays",
"/_authenticate/_inject-org-details/_org-layout/organization/networking",
"/_authenticate/_inject-org-details/_org-layout/organization/secret-sharing",
"/_authenticate/_inject-org-details/_org-layout/organization/settings",
"/_authenticate/_inject-org-details/_org-layout/organization/groups/$groupId",
@@ -6366,18 +6301,11 @@ export const routeTree = rootRoute
"/_authenticate/_inject-org-details/_org-layout/organization/app-connections/$appConnection/oauth/callback"
]
},
"/_authenticate/_inject-org-details/_org-layout/organization/gateways": {
"/_authenticate/_inject-org-details/_org-layout/organization/networking": {
"filePath": "",
"parent": "/_authenticate/_inject-org-details/_org-layout/organization",
"children": [
"/_authenticate/_inject-org-details/_org-layout/organization/gateways/"
]
},
"/_authenticate/_inject-org-details/_org-layout/organization/relays": {
"filePath": "",
"parent": "/_authenticate/_inject-org-details/_org-layout/organization",
"children": [
"/_authenticate/_inject-org-details/_org-layout/organization/relays/"
"/_authenticate/_inject-org-details/_org-layout/organization/networking/"
]
},
"/_authenticate/_inject-org-details/_org-layout/organization/secret-sharing": {
@@ -6407,13 +6335,9 @@ export const routeTree = rootRoute
"filePath": "organization/AppConnections/AppConnectionsPage/route.tsx",
"parent": "/_authenticate/_inject-org-details/_org-layout/organization/app-connections"
},
"/_authenticate/_inject-org-details/_org-layout/organization/gateways/": {
"filePath": "organization/Gateways/GatewayListPage/route.tsx",
"parent": "/_authenticate/_inject-org-details/_org-layout/organization/gateways"
},
"/_authenticate/_inject-org-details/_org-layout/organization/relays/": {
"filePath": "organization/Gateways/Relay/RelayListPage/route.tsx",
"parent": "/_authenticate/_inject-org-details/_org-layout/organization/relays"
"/_authenticate/_inject-org-details/_org-layout/organization/networking/": {
"filePath": "organization/NetworkingPage/route.tsx",
"parent": "/_authenticate/_inject-org-details/_org-layout/organization/networking"
},
"/_authenticate/_inject-org-details/_org-layout/organization/secret-sharing/": {
"filePath": "organization/SecretSharingPage/route.tsx",

View File

@@ -40,8 +40,7 @@ const organizationRoutes = route("/organization", [
"organization/AppConnections/OauthCallbackPage/route.tsx"
)
]),
route("/gateways", [index("organization/Gateways/GatewayListPage/route.tsx")]),
route("/relays", [index("organization/Gateways/Relay/RelayListPage/route.tsx")])
route("/networking", [index("organization/NetworkingPage/route.tsx")])
]);
const secretManagerRoutes = route("/projects/secret-management/$projectId", [