mirror of
https://github.com/fosrl/pangolin.git
synced 2026-02-17 10:26:39 +00:00
Build client site resource associations and send messages
This commit is contained in:
@@ -90,7 +90,7 @@ export default function CreateInternalResourceDialog({
|
||||
mode: z.enum(["host", "cidr"]),
|
||||
destination: z.string().min(1),
|
||||
siteId: z.int().positive(t("createInternalResourceDialogPleaseSelectSite")),
|
||||
protocol: z.enum(["tcp", "udp"]),
|
||||
// protocol: z.enum(["tcp", "udp"]),
|
||||
// proxyPort: z.int()
|
||||
// .positive()
|
||||
// .min(1, t("createInternalResourceDialogProxyPortMin"))
|
||||
@@ -177,7 +177,7 @@ export default function CreateInternalResourceDialog({
|
||||
name: "",
|
||||
siteId: availableSites[0]?.siteId || 0,
|
||||
mode: "host",
|
||||
protocol: "tcp",
|
||||
// protocol: "tcp",
|
||||
// proxyPort: undefined,
|
||||
destination: "",
|
||||
// destinationPort: undefined,
|
||||
@@ -196,7 +196,7 @@ export default function CreateInternalResourceDialog({
|
||||
name: "",
|
||||
siteId: availableSites[0].siteId,
|
||||
mode: "host",
|
||||
protocol: "tcp",
|
||||
// protocol: "tcp",
|
||||
// proxyPort: undefined,
|
||||
destination: "",
|
||||
// destinationPort: undefined,
|
||||
@@ -260,35 +260,38 @@ export default function CreateInternalResourceDialog({
|
||||
{
|
||||
name: data.name,
|
||||
mode: data.mode,
|
||||
protocol: data.mode === "port" ? data.protocol : undefined,
|
||||
// protocol: data.protocol,
|
||||
// proxyPort: data.mode === "port" ? data.proxyPort : undefined,
|
||||
// destinationPort: data.mode === "port" ? data.destinationPort : undefined,
|
||||
destination: data.destination,
|
||||
enabled: true,
|
||||
alias: data.alias && typeof data.alias === "string" && data.alias.trim() ? data.alias : undefined
|
||||
alias: data.alias && typeof data.alias === "string" && data.alias.trim() ? data.alias : undefined,
|
||||
roleIds: data.roles ? data.roles.map((r) => parseInt(r.id)) : [],
|
||||
userIds: data.users ? data.users.map((u) => u.id) : [],
|
||||
clientIds: data.clients ? data.clients.map((c) => parseInt(c.id)) : []
|
||||
}
|
||||
);
|
||||
|
||||
const siteResourceId = response.data.data.siteResourceId;
|
||||
|
||||
// Set roles and users if provided
|
||||
if (data.roles && data.roles.length > 0) {
|
||||
await api.post(`/site-resource/${siteResourceId}/roles`, {
|
||||
roleIds: data.roles.map((r) => parseInt(r.id))
|
||||
});
|
||||
}
|
||||
// // Set roles and users if provided
|
||||
// if (data.roles && data.roles.length > 0) {
|
||||
// await api.post(`/site-resource/${siteResourceId}/roles`, {
|
||||
// roleIds: data.roles.map((r) => parseInt(r.id))
|
||||
// });
|
||||
// }
|
||||
|
||||
if (data.users && data.users.length > 0) {
|
||||
await api.post(`/site-resource/${siteResourceId}/users`, {
|
||||
userIds: data.users.map((u) => u.id)
|
||||
});
|
||||
}
|
||||
// if (data.users && data.users.length > 0) {
|
||||
// await api.post(`/site-resource/${siteResourceId}/users`, {
|
||||
// userIds: data.users.map((u) => u.id)
|
||||
// });
|
||||
// }
|
||||
|
||||
if (data.clients && data.clients.length > 0) {
|
||||
await api.post(`/site-resource/${siteResourceId}/clients`, {
|
||||
clientIds: data.clients.map((c) => parseInt(c.id))
|
||||
});
|
||||
}
|
||||
// if (data.clients && data.clients.length > 0) {
|
||||
// await api.post(`/site-resource/${siteResourceId}/clients`, {
|
||||
// clientIds: data.clients.map((c) => parseInt(c.id))
|
||||
// });
|
||||
// }
|
||||
|
||||
toast({
|
||||
title: t("createInternalResourceDialogSuccess"),
|
||||
@@ -444,7 +447,7 @@ export default function CreateInternalResourceDialog({
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
<SelectItem value="port">{t("createInternalResourceDialogModePort")}</SelectItem>
|
||||
{/* <SelectItem value="port">{t("createInternalResourceDialogModePort")}</SelectItem> */}
|
||||
<SelectItem value="host">{t("createInternalResourceDialogModeHost")}</SelectItem>
|
||||
<SelectItem value="cidr">{t("createInternalResourceDialogModeCidr")}</SelectItem>
|
||||
</SelectContent>
|
||||
@@ -535,7 +538,7 @@ export default function CreateInternalResourceDialog({
|
||||
<FormDescription>
|
||||
{mode === "host" && t("createInternalResourceDialogDestinationHostDescription")}
|
||||
{mode === "cidr" && t("createInternalResourceDialogDestinationCidrDescription")}
|
||||
{mode === "port" && t("createInternalResourceDialogDestinationIPDescription")}
|
||||
{/* {mode === "port" && t("createInternalResourceDialogDestinationIPDescription")} */}
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
|
||||
@@ -36,7 +36,6 @@ import { toast } from "@app/hooks/useToast";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { createApiClient, formatAxiosError } from "@app/lib/api";
|
||||
import { useEnvContext } from "@app/hooks/useEnvContext";
|
||||
import { Separator } from "@app/components/ui/separator";
|
||||
import { ListRolesResponse } from "@server/routers/role";
|
||||
import { ListUsersResponse } from "@server/routers/user";
|
||||
import { ListSiteResourceRolesResponse } from "@server/routers/siteResource/listSiteResourceRoles";
|
||||
@@ -52,12 +51,13 @@ type InternalResourceData = {
|
||||
name: string;
|
||||
orgId: string;
|
||||
siteName: string;
|
||||
mode: "host" | "cidr" | "port";
|
||||
protocol: string | null;
|
||||
proxyPort: number | null;
|
||||
// mode: "host" | "cidr" | "port";
|
||||
mode: "host" | "cidr";
|
||||
// protocol: string | null;
|
||||
// proxyPort: number | null;
|
||||
siteId: number;
|
||||
destination: string;
|
||||
destinationPort?: number | null;
|
||||
// destinationPort?: number | null;
|
||||
alias?: string | null;
|
||||
};
|
||||
|
||||
@@ -83,10 +83,10 @@ export default function EditInternalResourceDialog({
|
||||
const formSchema = z.object({
|
||||
name: z.string().min(1, t("editInternalResourceDialogNameRequired")).max(255, t("editInternalResourceDialogNameMaxLength")),
|
||||
mode: z.enum(["host", "cidr", "port"]),
|
||||
protocol: z.enum(["tcp", "udp"]).nullish(),
|
||||
proxyPort: z.int().positive().min(1, t("editInternalResourceDialogProxyPortMin")).max(65535, t("editInternalResourceDialogProxyPortMax")).nullish(),
|
||||
// protocol: z.enum(["tcp", "udp"]).nullish(),
|
||||
// proxyPort: z.int().positive().min(1, t("editInternalResourceDialogProxyPortMin")).max(65535, t("editInternalResourceDialogProxyPortMax")).nullish(),
|
||||
destination: z.string().min(1),
|
||||
destinationPort: z.int().positive().min(1, t("editInternalResourceDialogDestinationPortMin")).max(65535, t("editInternalResourceDialogDestinationPortMax")).nullish(),
|
||||
// destinationPort: z.int().positive().min(1, t("editInternalResourceDialogDestinationPortMin")).max(65535, t("editInternalResourceDialogDestinationPortMax")).nullish(),
|
||||
alias: z.string().nullish(),
|
||||
roles: z.array(
|
||||
z.object({
|
||||
@@ -107,42 +107,42 @@ export default function EditInternalResourceDialog({
|
||||
})
|
||||
).optional()
|
||||
})
|
||||
.refine(
|
||||
(data) => {
|
||||
if (data.mode === "port") {
|
||||
return data.protocol !== undefined && data.protocol !== null;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
{
|
||||
message: t("editInternalResourceDialogProtocol") + " is required for port mode",
|
||||
path: ["protocol"]
|
||||
}
|
||||
)
|
||||
.refine(
|
||||
(data) => {
|
||||
if (data.mode === "port") {
|
||||
return data.proxyPort !== undefined && data.proxyPort !== null;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
{
|
||||
message: t("editInternalResourceDialogSitePort") + " is required for port mode",
|
||||
path: ["proxyPort"]
|
||||
}
|
||||
)
|
||||
.refine(
|
||||
(data) => {
|
||||
if (data.mode === "port") {
|
||||
return data.destinationPort !== undefined && data.destinationPort !== null;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
{
|
||||
message: t("targetPort") + " is required for port mode",
|
||||
path: ["destinationPort"]
|
||||
}
|
||||
);
|
||||
// .refine(
|
||||
// (data) => {
|
||||
// if (data.mode === "port") {
|
||||
// return data.protocol !== undefined && data.protocol !== null;
|
||||
// }
|
||||
// return true;
|
||||
// },
|
||||
// {
|
||||
// message: t("editInternalResourceDialogProtocol") + " is required for port mode",
|
||||
// path: ["protocol"]
|
||||
// }
|
||||
// )
|
||||
// .refine(
|
||||
// (data) => {
|
||||
// if (data.mode === "port") {
|
||||
// return data.proxyPort !== undefined && data.proxyPort !== null;
|
||||
// }
|
||||
// return true;
|
||||
// },
|
||||
// {
|
||||
// message: t("editInternalResourceDialogSitePort") + " is required for port mode",
|
||||
// path: ["proxyPort"]
|
||||
// }
|
||||
// )
|
||||
// .refine(
|
||||
// (data) => {
|
||||
// if (data.mode === "port") {
|
||||
// return data.destinationPort !== undefined && data.destinationPort !== null;
|
||||
// }
|
||||
// return true;
|
||||
// },
|
||||
// {
|
||||
// message: t("targetPort") + " is required for port mode",
|
||||
// path: ["destinationPort"]
|
||||
// }
|
||||
// );
|
||||
|
||||
type FormData = z.infer<typeof formSchema>;
|
||||
|
||||
@@ -160,10 +160,10 @@ export default function EditInternalResourceDialog({
|
||||
defaultValues: {
|
||||
name: resource.name,
|
||||
mode: resource.mode || "host",
|
||||
protocol: (resource.protocol as "tcp" | "udp" | null | undefined) ?? undefined,
|
||||
proxyPort: resource.proxyPort ?? undefined,
|
||||
// protocol: (resource.protocol as "tcp" | "udp" | null | undefined) ?? undefined,
|
||||
// proxyPort: resource.proxyPort ?? undefined,
|
||||
destination: resource.destination || "",
|
||||
destinationPort: resource.destinationPort ?? undefined,
|
||||
// destinationPort: resource.destinationPort ?? undefined,
|
||||
alias: resource.alias ?? null,
|
||||
roles: [],
|
||||
users: [],
|
||||
@@ -277,10 +277,10 @@ export default function EditInternalResourceDialog({
|
||||
form.reset({
|
||||
name: resource.name,
|
||||
mode: resource.mode || "host",
|
||||
protocol: (resource.protocol as "tcp" | "udp" | null | undefined) ?? undefined,
|
||||
proxyPort: resource.proxyPort ?? undefined,
|
||||
// protocol: (resource.protocol as "tcp" | "udp" | null | undefined) ?? undefined,
|
||||
// proxyPort: resource.proxyPort ?? undefined,
|
||||
destination: resource.destination || "",
|
||||
destinationPort: resource.destinationPort ?? undefined,
|
||||
// destinationPort: resource.destinationPort ?? undefined,
|
||||
alias: resource.alias ?? null,
|
||||
roles: [],
|
||||
users: [],
|
||||
@@ -298,25 +298,28 @@ export default function EditInternalResourceDialog({
|
||||
await api.post(`/org/${orgId}/site/${resource.siteId}/resource/${resource.id}`, {
|
||||
name: data.name,
|
||||
mode: data.mode,
|
||||
protocol: data.mode === "port" ? data.protocol : null,
|
||||
proxyPort: data.mode === "port" ? data.proxyPort : null,
|
||||
destinationPort: data.mode === "port" ? data.destinationPort : null,
|
||||
// protocol: data.mode === "port" ? data.protocol : null,
|
||||
// proxyPort: data.mode === "port" ? data.proxyPort : null,
|
||||
// destinationPort: data.mode === "port" ? data.destinationPort : null,
|
||||
destination: data.destination,
|
||||
alias: data.alias && typeof data.alias === "string" && data.alias.trim() ? data.alias : null
|
||||
alias: data.alias && typeof data.alias === "string" && data.alias.trim() ? data.alias : null,
|
||||
roleIds: (data.roles || []).map((r) => parseInt(r.id)),
|
||||
userIds: (data.users || []).map((u) => u.id),
|
||||
clientIds: (data.clients || []).map((c) => parseInt(c.id))
|
||||
});
|
||||
|
||||
// Update roles, users, and clients
|
||||
await Promise.all([
|
||||
api.post(`/site-resource/${resource.id}/roles`, {
|
||||
roleIds: (data.roles || []).map((r) => parseInt(r.id))
|
||||
}),
|
||||
api.post(`/site-resource/${resource.id}/users`, {
|
||||
userIds: (data.users || []).map((u) => u.id)
|
||||
}),
|
||||
api.post(`/site-resource/${resource.id}/clients`, {
|
||||
clientIds: (data.clients || []).map((c) => parseInt(c.id))
|
||||
})
|
||||
]);
|
||||
// await Promise.all([
|
||||
// api.post(`/site-resource/${resource.id}/roles`, {
|
||||
// roleIds: (data.roles || []).map((r) => parseInt(r.id))
|
||||
// }),
|
||||
// api.post(`/site-resource/${resource.id}/users`, {
|
||||
// userIds: (data.users || []).map((u) => u.id)
|
||||
// }),
|
||||
// api.post(`/site-resource/${resource.id}/clients`, {
|
||||
// clientIds: (data.clients || []).map((c) => parseInt(c.id))
|
||||
// })
|
||||
// ]);
|
||||
|
||||
toast({
|
||||
title: t("editInternalResourceDialogSuccess"),
|
||||
@@ -384,7 +387,7 @@ export default function EditInternalResourceDialog({
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
<SelectItem value="port">{t("editInternalResourceDialogModePort")}</SelectItem>
|
||||
{/* <SelectItem value="port">{t("editInternalResourceDialogModePort")}</SelectItem> */}
|
||||
<SelectItem value="host">{t("editInternalResourceDialogModeHost")}</SelectItem>
|
||||
<SelectItem value="cidr">{t("editInternalResourceDialogModeCidr")}</SelectItem>
|
||||
</SelectContent>
|
||||
@@ -394,7 +397,7 @@ export default function EditInternalResourceDialog({
|
||||
)}
|
||||
/>
|
||||
|
||||
{mode === "port" && (
|
||||
{/* {mode === "port" && (
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<FormField
|
||||
control={form.control}
|
||||
@@ -439,7 +442,7 @@ export default function EditInternalResourceDialog({
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
)} */}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -459,14 +462,14 @@ export default function EditInternalResourceDialog({
|
||||
<FormDescription>
|
||||
{mode === "host" && t("editInternalResourceDialogDestinationHostDescription")}
|
||||
{mode === "cidr" && t("editInternalResourceDialogDestinationCidrDescription")}
|
||||
{mode === "port" && t("editInternalResourceDialogDestinationIPDescription")}
|
||||
{/* {mode === "port" && t("editInternalResourceDialogDestinationIPDescription")} */}
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
{mode === "port" && (
|
||||
{/* {mode === "port" && (
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="destinationPort"
|
||||
@@ -484,7 +487,7 @@ export default function EditInternalResourceDialog({
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
)} */}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuCheckboxItem
|
||||
} from "@app/components/ui/dropdown-menu";
|
||||
import { Button } from "@app/components/ui/button";
|
||||
@@ -164,13 +164,14 @@ export type InternalResourceRow = {
|
||||
orgId: string;
|
||||
siteName: string;
|
||||
siteAddress: string | null;
|
||||
mode: "host" | "cidr" | "port";
|
||||
protocol: string | null;
|
||||
proxyPort: number | null;
|
||||
// mode: "host" | "cidr" | "port";
|
||||
mode: "host" | "cidr";
|
||||
// protocol: string | null;
|
||||
// proxyPort: number | null;
|
||||
siteId: number;
|
||||
siteNiceId: string;
|
||||
destination: string;
|
||||
destinationPort: number | null;
|
||||
// destinationPort: number | null;
|
||||
alias: string | null;
|
||||
};
|
||||
|
||||
@@ -515,10 +516,14 @@ export default function ResourcesTable({
|
||||
>
|
||||
<StatusIcon status={overallStatus} />
|
||||
<span className="text-sm">
|
||||
{overallStatus === "online" && t("resourcesTableHealthy")}
|
||||
{overallStatus === "degraded" && t("resourcesTableDegraded")}
|
||||
{overallStatus === "offline" && t("resourcesTableOffline")}
|
||||
{overallStatus === "unknown" && t("resourcesTableUnknown")}
|
||||
{overallStatus === "online" &&
|
||||
t("resourcesTableHealthy")}
|
||||
{overallStatus === "degraded" &&
|
||||
t("resourcesTableDegraded")}
|
||||
{overallStatus === "offline" &&
|
||||
t("resourcesTableOffline")}
|
||||
{overallStatus === "unknown" &&
|
||||
t("resourcesTableUnknown")}
|
||||
</span>
|
||||
<ChevronDown className="h-3 w-3" />
|
||||
</Button>
|
||||
@@ -770,7 +775,11 @@ export default function ResourcesTable({
|
||||
<div className="flex flex-col items-end gap-1 p-3">
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="ghost" size="sm" className="h-7 w-7 p-0">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="h-7 w-7 p-0"
|
||||
>
|
||||
<Columns className="h-4 w-4" />
|
||||
<span className="sr-only">
|
||||
{t("columns") || "Columns"}
|
||||
@@ -786,10 +795,14 @@ export default function ResourcesTable({
|
||||
.getAllColumns()
|
||||
.filter((column) => column.getCanHide())
|
||||
.map((column) => {
|
||||
const columnDef = column.columnDef as any;
|
||||
const friendlyName = columnDef.friendlyName;
|
||||
const displayName = friendlyName ||
|
||||
(typeof columnDef.header === "string"
|
||||
const columnDef =
|
||||
column.columnDef as any;
|
||||
const friendlyName =
|
||||
columnDef.friendlyName;
|
||||
const displayName =
|
||||
friendlyName ||
|
||||
(typeof columnDef.header ===
|
||||
"string"
|
||||
? columnDef.header
|
||||
: column.id);
|
||||
return (
|
||||
@@ -798,9 +811,13 @@ export default function ResourcesTable({
|
||||
className="capitalize"
|
||||
checked={column.getIsVisible()}
|
||||
onCheckedChange={(value) =>
|
||||
column.toggleVisibility(!!value)
|
||||
column.toggleVisibility(
|
||||
!!value
|
||||
)
|
||||
}
|
||||
onSelect={(e) =>
|
||||
e.preventDefault()
|
||||
}
|
||||
onSelect={(e) => e.preventDefault()}
|
||||
>
|
||||
{displayName}
|
||||
</DropdownMenuCheckboxItem>
|
||||
@@ -925,23 +942,24 @@ export default function ResourcesTable({
|
||||
let displayText: string;
|
||||
let copyText: string;
|
||||
|
||||
if (
|
||||
resourceRow.mode === "port" &&
|
||||
resourceRow.protocol &&
|
||||
resourceRow.proxyPort &&
|
||||
resourceRow.destinationPort
|
||||
) {
|
||||
const protocol = resourceRow.protocol.toUpperCase();
|
||||
// For port mode: site part uses alias or site address, destination part uses destination IP
|
||||
// If site address has CIDR notation, extract just the IP address
|
||||
let siteAddress = resourceRow.siteAddress;
|
||||
if (siteAddress && siteAddress.includes("/")) {
|
||||
siteAddress = siteAddress.split("/")[0];
|
||||
}
|
||||
const siteDisplay = resourceRow.alias || siteAddress;
|
||||
displayText = `${protocol} ${siteDisplay}:${resourceRow.proxyPort} -> ${resourceRow.destination}:${resourceRow.destinationPort}`;
|
||||
copyText = `${siteDisplay}:${resourceRow.proxyPort}`;
|
||||
} else if (resourceRow.mode === "host") {
|
||||
// if (
|
||||
// resourceRow.mode === "port" &&
|
||||
// // resourceRow.protocol &&
|
||||
// // resourceRow.proxyPort &&
|
||||
// // resourceRow.destinationPort
|
||||
// ) {
|
||||
// // const protocol = resourceRow.protocol.toUpperCase();
|
||||
// // For port mode: site part uses alias or site address, destination part uses destination IP
|
||||
// // If site address has CIDR notation, extract just the IP address
|
||||
// let siteAddress = resourceRow.siteAddress;
|
||||
// if (siteAddress && siteAddress.includes("/")) {
|
||||
// siteAddress = siteAddress.split("/")[0];
|
||||
// }
|
||||
// const siteDisplay = resourceRow.alias || siteAddress;
|
||||
// // displayText = `${protocol} ${siteDisplay}:${resourceRow.proxyPort} -> ${resourceRow.destination}:${resourceRow.destinationPort}`;
|
||||
// // copyText = `${siteDisplay}:${resourceRow.proxyPort}`;
|
||||
// } else if (resourceRow.mode === "host") {
|
||||
if (resourceRow.mode === "host") {
|
||||
// For host mode: use alias if available, otherwise use destination
|
||||
const destinationDisplay =
|
||||
resourceRow.alias || resourceRow.destination;
|
||||
@@ -981,7 +999,11 @@ export default function ResourcesTable({
|
||||
<div className="flex flex-col items-end gap-1 p-3">
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="outline" size="sm" className="h-7 w-7 p-0">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="h-7 w-7 p-0"
|
||||
>
|
||||
<Columns className="h-4 w-4" />
|
||||
<span className="sr-only">
|
||||
{t("columns") || "Columns"}
|
||||
@@ -997,10 +1019,14 @@ export default function ResourcesTable({
|
||||
.getAllColumns()
|
||||
.filter((column) => column.getCanHide())
|
||||
.map((column) => {
|
||||
const columnDef = column.columnDef as any;
|
||||
const friendlyName = columnDef.friendlyName;
|
||||
const displayName = friendlyName ||
|
||||
(typeof columnDef.header === "string"
|
||||
const columnDef =
|
||||
column.columnDef as any;
|
||||
const friendlyName =
|
||||
columnDef.friendlyName;
|
||||
const displayName =
|
||||
friendlyName ||
|
||||
(typeof columnDef.header ===
|
||||
"string"
|
||||
? columnDef.header
|
||||
: column.id);
|
||||
return (
|
||||
@@ -1009,9 +1035,13 @@ export default function ResourcesTable({
|
||||
className="capitalize"
|
||||
checked={column.getIsVisible()}
|
||||
onCheckedChange={(value) =>
|
||||
column.toggleVisibility(!!value)
|
||||
column.toggleVisibility(
|
||||
!!value
|
||||
)
|
||||
}
|
||||
onSelect={(e) =>
|
||||
e.preventDefault()
|
||||
}
|
||||
onSelect={(e) => e.preventDefault()}
|
||||
>
|
||||
{displayName}
|
||||
</DropdownMenuCheckboxItem>
|
||||
@@ -1230,99 +1260,111 @@ export default function ResourcesTable({
|
||||
<TabsContent value="proxy">
|
||||
<div className="overflow-x-auto">
|
||||
<Table>
|
||||
<TableHeader>
|
||||
{proxyTable
|
||||
.getHeaderGroups()
|
||||
.map((headerGroup) => (
|
||||
<TableRow key={headerGroup.id}>
|
||||
{headerGroup.headers
|
||||
.filter((header) =>
|
||||
header.column.getIsVisible()
|
||||
)
|
||||
.map((header) => (
|
||||
<TableHead
|
||||
key={header.id}
|
||||
className={`whitespace-nowrap ${
|
||||
header.column.id ===
|
||||
"actions"
|
||||
? "sticky right-0 z-10 w-auto min-w-fit bg-card"
|
||||
: header.column.id ===
|
||||
"name"
|
||||
? "md:sticky md:left-0 z-10 bg-card"
|
||||
: ""
|
||||
}`}
|
||||
>
|
||||
{header.isPlaceholder
|
||||
? null
|
||||
: flexRender(
|
||||
header
|
||||
.column
|
||||
.columnDef
|
||||
.header,
|
||||
header.getContext()
|
||||
)}
|
||||
</TableHead>
|
||||
))}
|
||||
</TableRow>
|
||||
))}
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{proxyTable.getRowModel().rows
|
||||
?.length ? (
|
||||
proxyTable
|
||||
.getRowModel()
|
||||
.rows.map((row) => (
|
||||
<TableHeader>
|
||||
{proxyTable
|
||||
.getHeaderGroups()
|
||||
.map((headerGroup) => (
|
||||
<TableRow
|
||||
key={row.id}
|
||||
data-state={
|
||||
row.getIsSelected() &&
|
||||
"selected"
|
||||
}
|
||||
key={headerGroup.id}
|
||||
>
|
||||
{row
|
||||
.getVisibleCells()
|
||||
.map((cell) => (
|
||||
<TableCell
|
||||
{headerGroup.headers
|
||||
.filter((header) =>
|
||||
header.column.getIsVisible()
|
||||
)
|
||||
.map((header) => (
|
||||
<TableHead
|
||||
key={
|
||||
cell.id
|
||||
header.id
|
||||
}
|
||||
className={`whitespace-nowrap ${
|
||||
cell.column.id ===
|
||||
header
|
||||
.column
|
||||
.id ===
|
||||
"actions"
|
||||
? "sticky right-0 z-10 w-auto min-w-fit bg-card"
|
||||
: cell.column.id ===
|
||||
"name"
|
||||
? "md:sticky md:left-0 z-10 bg-card"
|
||||
: ""
|
||||
: header
|
||||
.column
|
||||
.id ===
|
||||
"name"
|
||||
? "md:sticky md:left-0 z-10 bg-card"
|
||||
: ""
|
||||
}`}
|
||||
>
|
||||
{flexRender(
|
||||
cell
|
||||
.column
|
||||
.columnDef
|
||||
.cell,
|
||||
cell.getContext()
|
||||
)}
|
||||
</TableCell>
|
||||
{header.isPlaceholder
|
||||
? null
|
||||
: flexRender(
|
||||
header
|
||||
.column
|
||||
.columnDef
|
||||
.header,
|
||||
header.getContext()
|
||||
)}
|
||||
</TableHead>
|
||||
))}
|
||||
</TableRow>
|
||||
))
|
||||
) : (
|
||||
<TableRow>
|
||||
<TableCell
|
||||
colSpan={
|
||||
proxyColumns.length
|
||||
}
|
||||
className="h-24 text-center"
|
||||
>
|
||||
{t(
|
||||
"resourcesTableNoProxyResourcesFound"
|
||||
)}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
</TableBody>
|
||||
</Table>
|
||||
))}
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{proxyTable.getRowModel().rows
|
||||
?.length ? (
|
||||
proxyTable
|
||||
.getRowModel()
|
||||
.rows.map((row) => (
|
||||
<TableRow
|
||||
key={row.id}
|
||||
data-state={
|
||||
row.getIsSelected() &&
|
||||
"selected"
|
||||
}
|
||||
>
|
||||
{row
|
||||
.getVisibleCells()
|
||||
.map((cell) => (
|
||||
<TableCell
|
||||
key={
|
||||
cell.id
|
||||
}
|
||||
className={`whitespace-nowrap ${
|
||||
cell
|
||||
.column
|
||||
.id ===
|
||||
"actions"
|
||||
? "sticky right-0 z-10 w-auto min-w-fit bg-card"
|
||||
: cell
|
||||
.column
|
||||
.id ===
|
||||
"name"
|
||||
? "md:sticky md:left-0 z-10 bg-card"
|
||||
: ""
|
||||
}`}
|
||||
>
|
||||
{flexRender(
|
||||
cell
|
||||
.column
|
||||
.columnDef
|
||||
.cell,
|
||||
cell.getContext()
|
||||
)}
|
||||
</TableCell>
|
||||
))}
|
||||
</TableRow>
|
||||
))
|
||||
) : (
|
||||
<TableRow>
|
||||
<TableCell
|
||||
colSpan={
|
||||
proxyColumns.length
|
||||
}
|
||||
className="h-24 text-center"
|
||||
>
|
||||
{t(
|
||||
"resourcesTableNoProxyResourcesFound"
|
||||
)}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
<div className="mt-4">
|
||||
<DataTablePagination
|
||||
@@ -1336,99 +1378,111 @@ export default function ResourcesTable({
|
||||
<TabsContent value="internal">
|
||||
<div className="overflow-x-auto">
|
||||
<Table>
|
||||
<TableHeader>
|
||||
{internalTable
|
||||
.getHeaderGroups()
|
||||
.map((headerGroup) => (
|
||||
<TableRow key={headerGroup.id}>
|
||||
{headerGroup.headers
|
||||
.filter((header) =>
|
||||
header.column.getIsVisible()
|
||||
)
|
||||
.map((header) => (
|
||||
<TableHead
|
||||
key={header.id}
|
||||
className={`whitespace-nowrap ${
|
||||
header.column.id ===
|
||||
"actions"
|
||||
? "sticky right-0 z-10 w-auto min-w-fit bg-card"
|
||||
: header.column.id ===
|
||||
"name"
|
||||
? "md:sticky md:left-0 z-10 bg-card"
|
||||
: ""
|
||||
}`}
|
||||
>
|
||||
{header.isPlaceholder
|
||||
? null
|
||||
: flexRender(
|
||||
header
|
||||
.column
|
||||
.columnDef
|
||||
.header,
|
||||
header.getContext()
|
||||
)}
|
||||
</TableHead>
|
||||
))}
|
||||
</TableRow>
|
||||
))}
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{internalTable.getRowModel().rows
|
||||
?.length ? (
|
||||
internalTable
|
||||
.getRowModel()
|
||||
.rows.map((row) => (
|
||||
<TableHeader>
|
||||
{internalTable
|
||||
.getHeaderGroups()
|
||||
.map((headerGroup) => (
|
||||
<TableRow
|
||||
key={row.id}
|
||||
data-state={
|
||||
row.getIsSelected() &&
|
||||
"selected"
|
||||
}
|
||||
key={headerGroup.id}
|
||||
>
|
||||
{row
|
||||
.getVisibleCells()
|
||||
.map((cell) => (
|
||||
<TableCell
|
||||
{headerGroup.headers
|
||||
.filter((header) =>
|
||||
header.column.getIsVisible()
|
||||
)
|
||||
.map((header) => (
|
||||
<TableHead
|
||||
key={
|
||||
cell.id
|
||||
header.id
|
||||
}
|
||||
className={`whitespace-nowrap ${
|
||||
cell.column.id ===
|
||||
header
|
||||
.column
|
||||
.id ===
|
||||
"actions"
|
||||
? "sticky right-0 z-10 w-auto min-w-fit bg-card"
|
||||
: cell.column.id ===
|
||||
"name"
|
||||
? "md:sticky md:left-0 z-10 bg-card"
|
||||
: ""
|
||||
: header
|
||||
.column
|
||||
.id ===
|
||||
"name"
|
||||
? "md:sticky md:left-0 z-10 bg-card"
|
||||
: ""
|
||||
}`}
|
||||
>
|
||||
{flexRender(
|
||||
cell
|
||||
.column
|
||||
.columnDef
|
||||
.cell,
|
||||
cell.getContext()
|
||||
)}
|
||||
</TableCell>
|
||||
{header.isPlaceholder
|
||||
? null
|
||||
: flexRender(
|
||||
header
|
||||
.column
|
||||
.columnDef
|
||||
.header,
|
||||
header.getContext()
|
||||
)}
|
||||
</TableHead>
|
||||
))}
|
||||
</TableRow>
|
||||
))
|
||||
) : (
|
||||
<TableRow>
|
||||
<TableCell
|
||||
colSpan={
|
||||
internalColumns.length
|
||||
}
|
||||
className="h-24 text-center"
|
||||
>
|
||||
{t(
|
||||
"resourcesTableNoInternalResourcesFound"
|
||||
)}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
</TableBody>
|
||||
</Table>
|
||||
))}
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{internalTable.getRowModel().rows
|
||||
?.length ? (
|
||||
internalTable
|
||||
.getRowModel()
|
||||
.rows.map((row) => (
|
||||
<TableRow
|
||||
key={row.id}
|
||||
data-state={
|
||||
row.getIsSelected() &&
|
||||
"selected"
|
||||
}
|
||||
>
|
||||
{row
|
||||
.getVisibleCells()
|
||||
.map((cell) => (
|
||||
<TableCell
|
||||
key={
|
||||
cell.id
|
||||
}
|
||||
className={`whitespace-nowrap ${
|
||||
cell
|
||||
.column
|
||||
.id ===
|
||||
"actions"
|
||||
? "sticky right-0 z-10 w-auto min-w-fit bg-card"
|
||||
: cell
|
||||
.column
|
||||
.id ===
|
||||
"name"
|
||||
? "md:sticky md:left-0 z-10 bg-card"
|
||||
: ""
|
||||
}`}
|
||||
>
|
||||
{flexRender(
|
||||
cell
|
||||
.column
|
||||
.columnDef
|
||||
.cell,
|
||||
cell.getContext()
|
||||
)}
|
||||
</TableCell>
|
||||
))}
|
||||
</TableRow>
|
||||
))
|
||||
) : (
|
||||
<TableRow>
|
||||
<TableCell
|
||||
colSpan={
|
||||
internalColumns.length
|
||||
}
|
||||
className="h-24 text-center"
|
||||
>
|
||||
{t(
|
||||
"resourcesTableNoInternalResourcesFound"
|
||||
)}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
<div className="mt-4">
|
||||
<DataTablePagination
|
||||
|
||||
Reference in New Issue
Block a user