mirror of
https://github.com/fosrl/pangolin.git
synced 2026-02-20 11:56:38 +00:00
more sidebar improvements
This commit is contained in:
@@ -649,7 +649,7 @@
|
||||
"resourcesUsersRolesAccess": "User and role-based access control",
|
||||
"resourcesErrorUpdate": "Failed to toggle resource",
|
||||
"resourcesErrorUpdateDescription": "An error occurred while updating the resource",
|
||||
"access": "Access",
|
||||
"access": "Access Control",
|
||||
"shareLink": "{resource} Share Link",
|
||||
"resourceSelect": "Select resource",
|
||||
"shareLinks": "Share Links",
|
||||
@@ -790,6 +790,7 @@
|
||||
"accessRoleRemoved": "Role removed",
|
||||
"accessRoleRemovedDescription": "The role has been successfully removed.",
|
||||
"accessRoleRequiredRemove": "Before deleting this role, please select a new role to transfer existing members to.",
|
||||
"network": "Network",
|
||||
"manage": "Manage",
|
||||
"sitesNotFound": "No sites found.",
|
||||
"pangolinServerAdmin": "Server Admin - Pangolin",
|
||||
@@ -1267,6 +1268,7 @@
|
||||
"sidebarLogAndAnalytics": "Log & Analytics",
|
||||
"sidebarBluePrints": "Blueprints",
|
||||
"sidebarOrganization": "Organization",
|
||||
"sidebarManagement": "Management",
|
||||
"sidebarBillingAndLicenses": "Billing & Licenses",
|
||||
"sidebarLogsAnalytics": "Analytics",
|
||||
"blueprints": "Blueprints",
|
||||
|
||||
@@ -2,6 +2,7 @@ import { SidebarNavItem } from "@app/components/SidebarNav";
|
||||
import { Env } from "@app/lib/types/env";
|
||||
import { build } from "@server/build";
|
||||
import {
|
||||
Building2,
|
||||
ChartLine,
|
||||
Combine,
|
||||
CreditCard,
|
||||
@@ -11,10 +12,11 @@ import {
|
||||
KeyRound,
|
||||
Laptop,
|
||||
Link as LinkIcon,
|
||||
Logs, // Added from 'dev' branch
|
||||
Logs,
|
||||
MonitorUp,
|
||||
Plug,
|
||||
ReceiptText,
|
||||
ScanEye, // Added from 'dev' branch
|
||||
ScanEye,
|
||||
Server,
|
||||
Settings,
|
||||
SquareMousePointer,
|
||||
@@ -49,12 +51,12 @@ export const orgNavSections = (
|
||||
options?: OrgNavSectionsOptions
|
||||
): SidebarNavSection[] => [
|
||||
{
|
||||
heading: "sidebarGeneral",
|
||||
heading: "network",
|
||||
items: [
|
||||
{
|
||||
title: "sidebarSites",
|
||||
href: "/{orgId}/settings/sites",
|
||||
icon: <Combine className="size-4 flex-none" />
|
||||
icon: <Plug className="size-4 flex-none" />
|
||||
},
|
||||
{
|
||||
title: "sidebarResources",
|
||||
@@ -157,92 +159,88 @@ export const orgNavSections = (
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
heading: "sidebarLogsAndAnalytics",
|
||||
items: (() => {
|
||||
const logItems: SidebarNavItem[] = [
|
||||
{
|
||||
title: "sidebarLogsRequest",
|
||||
href: "/{orgId}/settings/logs/request",
|
||||
icon: <SquareMousePointer className="size-4 flex-none" />
|
||||
},
|
||||
...(!env?.flags.disableEnterpriseFeatures
|
||||
? [
|
||||
{
|
||||
title: "sidebarLogsAccess",
|
||||
href: "/{orgId}/settings/logs/access",
|
||||
icon: <ScanEye className="size-4 flex-none" />
|
||||
},
|
||||
{
|
||||
title: "sidebarLogsAction",
|
||||
href: "/{orgId}/settings/logs/action",
|
||||
icon: <Logs className="size-4 flex-none" />
|
||||
}
|
||||
]
|
||||
: [])
|
||||
];
|
||||
|
||||
const analytics = {
|
||||
title: "sidebarLogsAnalytics",
|
||||
href: "/{orgId}/settings/logs/analytics",
|
||||
icon: <ChartLine className="h-4 w-4" />
|
||||
};
|
||||
|
||||
// If only one log item, return it directly without grouping
|
||||
if (logItems.length === 1) {
|
||||
return [analytics, ...logItems];
|
||||
}
|
||||
|
||||
// If multiple log items, create a group
|
||||
return [
|
||||
analytics,
|
||||
{
|
||||
title: "sidebarLogs",
|
||||
icon: <Logs className="size-4 flex-none" />,
|
||||
items: logItems
|
||||
}
|
||||
];
|
||||
})()
|
||||
},
|
||||
{
|
||||
heading: "sidebarOrganization",
|
||||
items: [
|
||||
{
|
||||
title: "sidebarApiKeys",
|
||||
href: "/{orgId}/settings/api-keys",
|
||||
icon: <KeyRound className="size-4 flex-none" />
|
||||
title: "sidebarLogsAndAnalytics",
|
||||
icon: <ChartLine className="size-4 flex-none" />,
|
||||
items: [
|
||||
{
|
||||
title: "sidebarLogsAnalytics",
|
||||
href: "/{orgId}/settings/logs/analytics",
|
||||
icon: <ChartLine className="size-4 flex-none" />
|
||||
},
|
||||
{
|
||||
title: "sidebarLogsRequest",
|
||||
href: "/{orgId}/settings/logs/request",
|
||||
icon: (
|
||||
<SquareMousePointer className="size-4 flex-none" />
|
||||
)
|
||||
},
|
||||
...(!env?.flags.disableEnterpriseFeatures
|
||||
? [
|
||||
{
|
||||
title: "sidebarLogsAccess",
|
||||
href: "/{orgId}/settings/logs/access",
|
||||
icon: <ScanEye className="size-4 flex-none" />
|
||||
},
|
||||
{
|
||||
title: "sidebarLogsAction",
|
||||
href: "/{orgId}/settings/logs/action",
|
||||
icon: <Logs className="size-4 flex-none" />
|
||||
}
|
||||
]
|
||||
: [])
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "sidebarBluePrints",
|
||||
href: "/{orgId}/settings/blueprints",
|
||||
icon: <ReceiptText className="size-4 flex-none" />
|
||||
title: "sidebarManagement",
|
||||
icon: <Building2 className="size-4 flex-none" />,
|
||||
items: [
|
||||
{
|
||||
title: "sidebarApiKeys",
|
||||
href: "/{orgId}/settings/api-keys",
|
||||
icon: <KeyRound className="size-4 flex-none" />
|
||||
},
|
||||
{
|
||||
title: "sidebarBluePrints",
|
||||
href: "/{orgId}/settings/blueprints",
|
||||
icon: <ReceiptText className="size-4 flex-none" />
|
||||
}
|
||||
]
|
||||
},
|
||||
...(build == "saas" && options?.isPrimaryOrg
|
||||
? [
|
||||
{
|
||||
title: "sidebarBillingAndLicenses",
|
||||
icon: <CreditCard className="size-4 flex-none" />,
|
||||
items: [
|
||||
{
|
||||
title: "sidebarBilling",
|
||||
href: "/{orgId}/settings/billing",
|
||||
icon: (
|
||||
<CreditCard className="size-4 flex-none" />
|
||||
)
|
||||
},
|
||||
{
|
||||
title: "sidebarEnterpriseLicenses",
|
||||
href: "/{orgId}/settings/license",
|
||||
icon: (
|
||||
<TicketCheck className="size-4 flex-none" />
|
||||
)
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
: []),
|
||||
{
|
||||
title: "sidebarSettings",
|
||||
href: "/{orgId}/settings/general",
|
||||
icon: <Settings className="size-4 flex-none" />
|
||||
}
|
||||
]
|
||||
},
|
||||
...(build == "saas" && options?.isPrimaryOrg
|
||||
? [
|
||||
{
|
||||
heading: "sidebarBillingAndLicenses",
|
||||
items: [
|
||||
{
|
||||
title: "sidebarBilling",
|
||||
href: "/{orgId}/settings/billing",
|
||||
icon: <CreditCard className="size-4 flex-none" />
|
||||
},
|
||||
{
|
||||
title: "sidebarEnterpriseLicenses",
|
||||
href: "/{orgId}/settings/license",
|
||||
icon: <TicketCheck className="size-4 flex-none" />
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
: [])
|
||||
}
|
||||
];
|
||||
|
||||
export const adminNavSections = (env?: Env): SidebarNavSection[] => [
|
||||
|
||||
@@ -18,7 +18,7 @@ import { approvalQueries } from "@app/lib/queries";
|
||||
import { build } from "@server/build";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { ListUserOrgsResponse } from "@server/routers/org";
|
||||
import { ExternalLink, Server } from "lucide-react";
|
||||
import { ArrowRight, ExternalLink, Server } from "lucide-react";
|
||||
import { useTranslations } from "next-intl";
|
||||
import dynamic from "next/dynamic";
|
||||
import Link from "next/link";
|
||||
@@ -146,36 +146,6 @@ export function LayoutSidebar({
|
||||
/>
|
||||
<div className="flex-1 overflow-y-auto relative">
|
||||
<div className="px-2 pt-1">
|
||||
{!isAdminPage && user.serverAdmin && (
|
||||
<div className="py-2">
|
||||
<Link
|
||||
href="/admin"
|
||||
className={cn(
|
||||
"flex items-center transition-colors text-muted-foreground hover:text-foreground text-sm w-full hover:bg-secondary/80 dark:hover:bg-secondary/50 rounded-md",
|
||||
isSidebarCollapsed
|
||||
? "px-2 py-2 justify-center"
|
||||
: "px-3 py-1.5"
|
||||
)}
|
||||
title={
|
||||
isSidebarCollapsed
|
||||
? t("serverAdmin")
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
<span
|
||||
className={cn(
|
||||
"shrink-0",
|
||||
!isSidebarCollapsed && "mr-2"
|
||||
)}
|
||||
>
|
||||
<Server className="h-4 w-4" />
|
||||
</span>
|
||||
{!isSidebarCollapsed && (
|
||||
<span>{t("serverAdmin")}</span>
|
||||
)}
|
||||
</Link>
|
||||
</div>
|
||||
)}
|
||||
<SidebarNav
|
||||
sections={navItems}
|
||||
isCollapsed={isSidebarCollapsed}
|
||||
@@ -186,6 +156,40 @@ export function LayoutSidebar({
|
||||
<div className="sticky bottom-0 left-0 right-0 h-8 pointer-events-none bg-gradient-to-t from-card to-transparent" />
|
||||
</div>
|
||||
|
||||
{!isAdminPage && user.serverAdmin && (
|
||||
<div className="shrink-0 px-2 pb-2">
|
||||
<Link
|
||||
href="/admin"
|
||||
className={cn(
|
||||
"flex items-center transition-colors text-muted-foreground hover:text-foreground text-sm w-full hover:bg-secondary/80 dark:hover:bg-secondary/50 rounded-md",
|
||||
isSidebarCollapsed
|
||||
? "px-2 py-2 justify-center"
|
||||
: "px-3 py-1.5"
|
||||
)}
|
||||
title={
|
||||
isSidebarCollapsed
|
||||
? t("serverAdmin")
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
<span
|
||||
className={cn(
|
||||
"shrink-0",
|
||||
!isSidebarCollapsed && "mr-2"
|
||||
)}
|
||||
>
|
||||
<Server className="h-4 w-4" />
|
||||
</span>
|
||||
{!isSidebarCollapsed && (
|
||||
<>
|
||||
<span className="flex-1">{t("serverAdmin")}</span>
|
||||
<ArrowRight className="h-4 w-4 shrink-0 ml-auto opacity-70" />
|
||||
</>
|
||||
)}
|
||||
</Link>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="w-full border-t border-border" />
|
||||
|
||||
<div className="p-4 pt-1 flex flex-col shrink-0">
|
||||
|
||||
@@ -71,7 +71,7 @@ export function OrgSelector({
|
||||
"cursor-pointer transition-colors",
|
||||
isCollapsed
|
||||
? "w-full h-16 flex items-center justify-center hover:bg-muted"
|
||||
: "w-full px-4 py-4 hover:bg-muted"
|
||||
: "w-full px-5 py-4 hover:bg-muted"
|
||||
)}
|
||||
>
|
||||
{isCollapsed ? (
|
||||
|
||||
Reference in New Issue
Block a user