Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions backend/internal/repository/acl_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,12 @@ func (r *ACLRepository) ListGroups(params ACLGroupListParams) ([]models.ACLGroup
offset := (params.Page - 1) * params.Limit
query = query.Offset(offset).Limit(params.Limit)

// Preload creator relation
query = query.Preload("Creator")
// Preload relations
query = query.Preload("Creator").
Preload("IPRules").
Preload("BasicAuthUsers").
Preload("WaygatesAuth").
Preload("ExternalProviders")

// Execute query
if err := query.Find(&groups).Error; err != nil {
Expand Down
12 changes: 12 additions & 0 deletions ui/src/components/acl/group-usage-tab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ export function GroupUsageTab({ groupId }: GroupUsageTabProps) {
</div>
);
},
minSize: 140,
maxSize: 240,
meta: {
skeleton: (
<div className="flex items-center gap-2">
Expand Down Expand Up @@ -90,6 +92,8 @@ export function GroupUsageTab({ groupId }: GroupUsageTabProps) {
);
},
enableSorting: false,
minSize: 140,
maxSize: 260,
meta: {
skeleton: <Skeleton className="h-6 w-40" />,
},
Expand All @@ -103,6 +107,8 @@ export function GroupUsageTab({ groupId }: GroupUsageTabProps) {
</code>
),
enableSorting: false,
minSize: 80,
maxSize: 140,
meta: {
skeleton: <Skeleton className="h-6 w-16" />,
},
Expand All @@ -116,6 +122,8 @@ export function GroupUsageTab({ groupId }: GroupUsageTabProps) {
</Badge>
),
enableSorting: false,
minSize: 60,
maxSize: 100,
meta: {
skeleton: <Skeleton className="h-6 w-12 rounded-full" />,
},
Expand All @@ -130,6 +138,8 @@ export function GroupUsageTab({ groupId }: GroupUsageTabProps) {
<Badge variant="outline">Disabled</Badge>
),
enableSorting: false,
minSize: 70,
maxSize: 100,
meta: {
skeleton: <Skeleton className="h-6 w-16 rounded-full" />,
},
Expand Down Expand Up @@ -163,6 +173,8 @@ export function GroupUsageTab({ groupId }: GroupUsageTabProps) {
);
},
enableSorting: false,
minSize: 60,
maxSize: 80,
meta: {
skeleton: (
<div className="flex justify-end">
Expand Down
14 changes: 14 additions & 0 deletions ui/src/components/audit-logs/audit-data-grid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ export function AuditDataGrid({
</Tooltip>
);
},
minSize: 100,
maxSize: 160,
meta: {
skeleton: <Skeleton className="h-5 w-24" />,
},
Expand All @@ -80,6 +82,8 @@ export function AuditDataGrid({
header: 'Action',
cell: ({ row }) => <ActionBadge action={row.getValue('action')} />,
enableSorting: false,
minSize: 100,
maxSize: 160,
meta: {
skeleton: <Skeleton className="h-6 w-24 rounded-full" />,
},
Expand All @@ -104,6 +108,8 @@ export function AuditDataGrid({
);
},
enableSorting: false,
minSize: 140,
maxSize: 240,
meta: {
skeleton: <Skeleton className="h-5 w-32" />,
},
Expand All @@ -122,6 +128,8 @@ export function AuditDataGrid({
return <span className="text-muted-foreground italic">System</span>;
},
enableSorting: false,
minSize: 80,
maxSize: 140,
meta: {
skeleton: <Skeleton className="h-5 w-20" />,
},
Expand All @@ -131,6 +139,8 @@ export function AuditDataGrid({
header: 'Status',
cell: ({ row }) => <StatusBadge status={row.getValue('status')} />,
enableSorting: false,
minSize: 70,
maxSize: 100,
meta: {
skeleton: <Skeleton className="h-6 w-20 rounded-full" />,
},
Expand All @@ -147,6 +157,8 @@ export function AuditDataGrid({
);
},
enableSorting: false,
minSize: 80,
maxSize: 140,
meta: {
skeleton: <Skeleton className="h-5 w-28" />,
},
Expand Down Expand Up @@ -175,6 +187,8 @@ export function AuditDataGrid({
</div>
),
enableSorting: false,
minSize: 60,
maxSize: 80,
meta: {
skeleton: <Skeleton className="size-8 rounded" />,
},
Expand Down
62 changes: 59 additions & 3 deletions ui/src/components/proxy/cells/proxy-target-cell.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,76 @@
import { Badge, Tooltip, TooltipContent, TooltipTrigger } from '@e412/titanium';
import { Server } from 'lucide-react';
import type { ProxyConfig } from '@/types/proxy';

interface ProxyTargetCellProps {
proxy: ProxyConfig;
}

function formatUpstream(upstream: { scheme: string; host: string; port: number }): string {
return `${upstream.scheme}://${upstream.host}:${upstream.port}`;
}

export function ProxyTargetCell({ proxy }: ProxyTargetCellProps) {
const target = getProxyTarget(proxy);
if (proxy.type === 'reverse_proxy' && proxy.upstreams?.length) {
const count = proxy.upstreams.length;

if (count === 1) {
return (
<Badge variant="secondary" className="font-mono text-xs">
{formatUpstream(proxy.upstreams[0])}
</Badge>
);
}

return (
<Tooltip>
<TooltipTrigger asChild>
<div className="flex items-center gap-2">
<Badge variant="secondary" className="font-mono text-xs shrink-0">
{formatUpstream(proxy.upstreams[0])}
</Badge>
<Badge variant="outline" className="text-xs shrink-0 gap-1">
<Server className="size-3" />+{count - 1}
</Badge>
</div>
</TooltipTrigger>
<TooltipContent side="bottom" align="start">
<div className="space-y-1">
{proxy.upstreams.map((u) => (
<div key={`${u.host}:${u.port}`} className="font-mono text-xs">
{formatUpstream(u)}
</div>
))}
</div>
</TooltipContent>
</Tooltip>
);
}

if (proxy.type === 'redirect' && proxy.redirect) {
return (
<Badge variant="secondary" className="font-mono text-xs max-w-[250px] truncate">
{proxy.redirect.target}
</Badge>
);
}

if (proxy.type === 'static' && proxy.static) {
return (
<Badge variant="secondary" className="font-mono text-xs">
{proxy.static.root_path}
</Badge>
);
}

return <span className="text-muted-foreground max-w-[200px] truncate block">{target}</span>;
return <span className="text-muted-foreground">-</span>;
}

export function getProxyTarget(proxy: ProxyConfig): string {
if (proxy.type === 'reverse_proxy' && proxy.upstreams?.length) {
const upstream = proxy.upstreams[0];
const count = proxy.upstreams.length;
const target = `${upstream.scheme}://${upstream.host}:${upstream.port}`;
const target = formatUpstream(upstream);
return count > 1 ? `${target} (+${count - 1} more)` : target;
}

Expand Down
Loading