mirror of
https://github.com/fosrl/pangolin.git
synced 2026-09-11 13:31:27 +02:00
cosmetic adjustments
This commit is contained in:
@@ -1,19 +1,18 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DropdownMenu,
|
|
||||||
DropdownMenuContent,
|
|
||||||
DropdownMenuItem,
|
DropdownMenuItem,
|
||||||
DropdownMenuTrigger
|
DropdownMenuSub,
|
||||||
|
DropdownMenuSubContent,
|
||||||
|
DropdownMenuSubTrigger
|
||||||
} from "@app/components/ui/dropdown-menu";
|
} from "@app/components/ui/dropdown-menu";
|
||||||
import { Button } from "@app/components/ui/button";
|
import { Check, Languages } from "lucide-react";
|
||||||
import { Check, Globe, Languages } from "lucide-react";
|
|
||||||
import clsx from "clsx";
|
|
||||||
import { useTransition } from "react";
|
import { useTransition } from "react";
|
||||||
import { Locale } from "@/i18n/config";
|
import { Locale } from "@/i18n/config";
|
||||||
import { setUserLocale } from "@/services/locale";
|
import { setUserLocale } from "@/services/locale";
|
||||||
import { createApiClient } from "@app/lib/api";
|
import { createApiClient } from "@app/lib/api";
|
||||||
import { useEnvContext } from "@app/hooks/useEnvContext";
|
import { useEnvContext } from "@app/hooks/useEnvContext";
|
||||||
|
import { cn } from "@app/lib/cn";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
defaultValue: string;
|
defaultValue: string;
|
||||||
@@ -43,23 +42,18 @@ export default function LocaleSwitcherSelect({
|
|||||||
const selected = items.find((item) => item.value === defaultValue);
|
const selected = items.find((item) => item.value === defaultValue);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DropdownMenu>
|
<DropdownMenuSub>
|
||||||
<DropdownMenuTrigger asChild>
|
<DropdownMenuSubTrigger
|
||||||
<Button
|
className={cn(
|
||||||
variant="ghost"
|
"[&_svg:not([class*='text-'])]:text-muted-foreground",
|
||||||
className={clsx(
|
isPending && "pointer-events-none"
|
||||||
"w-full rounded-sm h-8 gap-2 justify-start font-normal",
|
)}
|
||||||
isPending && "pointer-events-none"
|
aria-label={label}
|
||||||
)}
|
>
|
||||||
aria-label={label}
|
<Languages className="mr-2 h-4 w-4" />
|
||||||
>
|
<span>{selected?.label ?? label}</span>
|
||||||
<Languages className="text-muted-foreground h-4 w-4" />
|
</DropdownMenuSubTrigger>
|
||||||
<span className="text-left flex-1">
|
<DropdownMenuSubContent className="min-w-[8rem]">
|
||||||
{selected?.label ?? label}
|
|
||||||
</span>
|
|
||||||
</Button>
|
|
||||||
</DropdownMenuTrigger>
|
|
||||||
<DropdownMenuContent align="end" className="min-w-[8rem]">
|
|
||||||
{items.map((item) => (
|
{items.map((item) => (
|
||||||
<DropdownMenuItem
|
<DropdownMenuItem
|
||||||
key={item.value}
|
key={item.value}
|
||||||
@@ -72,7 +66,7 @@ export default function LocaleSwitcherSelect({
|
|||||||
<span>{item.label}</span>
|
<span>{item.label}</span>
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
))}
|
))}
|
||||||
</DropdownMenuContent>
|
</DropdownMenuSubContent>
|
||||||
</DropdownMenu>
|
</DropdownMenuSub>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,15 +27,7 @@ export function OrgSelector({
|
|||||||
const selectedOrg = orgs?.find((org) => org.orgId === orgId);
|
const selectedOrg = orgs?.find((org) => org.orgId === orgId);
|
||||||
|
|
||||||
const picker = (
|
const picker = (
|
||||||
<OrgPicker
|
<OrgPicker orgId={orgId} orgs={orgs} contentClassName="w-[320px]">
|
||||||
orgId={orgId}
|
|
||||||
orgs={orgs}
|
|
||||||
contentClassName={
|
|
||||||
isCollapsed
|
|
||||||
? "w-[320px]"
|
|
||||||
: "w-[var(--radix-popover-trigger-width)]"
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
role="combobox"
|
role="combobox"
|
||||||
className={cn(
|
className={cn(
|
||||||
|
|||||||
@@ -103,6 +103,11 @@ export default function OrgsTable({
|
|||||||
enableHiding: false,
|
enableHiding: false,
|
||||||
header: () => sortableHeader("name", t("name"))
|
header: () => sortableHeader("name", t("name"))
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "orgId",
|
||||||
|
friendlyName: t("orgId"),
|
||||||
|
header: () => <span className="p-3">{t("orgId")}</span>
|
||||||
|
},
|
||||||
{
|
{
|
||||||
accessorKey: "createdAt",
|
accessorKey: "createdAt",
|
||||||
friendlyName: t("createdAt"),
|
friendlyName: t("createdAt"),
|
||||||
@@ -141,11 +146,6 @@ export default function OrgsTable({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
accessorKey: "orgId",
|
|
||||||
friendlyName: t("orgId"),
|
|
||||||
header: () => <span className="p-3">{t("orgId")}</span>
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
accessorKey: "subnet",
|
accessorKey: "subnet",
|
||||||
friendlyName: t("subnet"),
|
friendlyName: t("subnet"),
|
||||||
@@ -164,31 +164,19 @@ export default function OrgsTable({
|
|||||||
accessorKey: "userCount",
|
accessorKey: "userCount",
|
||||||
friendlyName: t("users"),
|
friendlyName: t("users"),
|
||||||
header: () => <span className="p-3">{t("users")}</span>,
|
header: () => <span className="p-3">{t("users")}</span>,
|
||||||
cell: ({ row }) => (
|
cell: ({ row }) => <span>{row.original.userCount}</span>
|
||||||
<span className="tabular-nums">
|
|
||||||
{row.original.userCount}
|
|
||||||
</span>
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessorKey: "siteCount",
|
accessorKey: "siteCount",
|
||||||
friendlyName: t("sites"),
|
friendlyName: t("sites"),
|
||||||
header: () => <span className="p-3">{t("sites")}</span>,
|
header: () => <span className="p-3">{t("sites")}</span>,
|
||||||
cell: ({ row }) => (
|
cell: ({ row }) => <span>{row.original.siteCount}</span>
|
||||||
<span className="tabular-nums">
|
|
||||||
{row.original.siteCount}
|
|
||||||
</span>
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessorKey: "resourceCount",
|
accessorKey: "resourceCount",
|
||||||
friendlyName: t("resources"),
|
friendlyName: t("resources"),
|
||||||
header: () => <span className="p-3">{t("resources")}</span>,
|
header: () => <span className="p-3">{t("resources")}</span>,
|
||||||
cell: ({ row }) => (
|
cell: ({ row }) => <span>{row.original.resourceCount}</span>
|
||||||
<span className="tabular-nums">
|
|
||||||
{row.original.resourceCount}
|
|
||||||
</span>
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -205,7 +193,6 @@ export default function OrgsTable({
|
|||||||
setIsDeleteModalOpen(true);
|
setIsDeleteModalOpen(true);
|
||||||
}}
|
}}
|
||||||
variant="outline"
|
variant="outline"
|
||||||
className="text-red-400 focus:text-destructive "
|
|
||||||
>
|
>
|
||||||
{t("delete")}
|
{t("delete")}
|
||||||
</Button>
|
</Button>
|
||||||
@@ -288,8 +275,7 @@ export default function OrgsTable({
|
|||||||
rowCount={rowCount}
|
rowCount={rowCount}
|
||||||
columnVisibility={{
|
columnVisibility={{
|
||||||
subnet: false,
|
subnet: false,
|
||||||
utilitySubnet: false,
|
utilitySubnet: false
|
||||||
orgId: false
|
|
||||||
}}
|
}}
|
||||||
enableColumnVisibility
|
enableColumnVisibility
|
||||||
stickyLeftColumn="name"
|
stickyLeftColumn="name"
|
||||||
|
|||||||
@@ -9,13 +9,16 @@ import {
|
|||||||
DropdownMenuItem,
|
DropdownMenuItem,
|
||||||
DropdownMenuLabel,
|
DropdownMenuLabel,
|
||||||
DropdownMenuSeparator,
|
DropdownMenuSeparator,
|
||||||
|
DropdownMenuSub,
|
||||||
|
DropdownMenuSubContent,
|
||||||
|
DropdownMenuSubTrigger,
|
||||||
DropdownMenuTrigger
|
DropdownMenuTrigger
|
||||||
} from "@app/components/ui/dropdown-menu";
|
} from "@app/components/ui/dropdown-menu";
|
||||||
import { useEnvContext } from "@app/hooks/useEnvContext";
|
import { useEnvContext } from "@app/hooks/useEnvContext";
|
||||||
import { toast } from "@app/hooks/useToast";
|
import { toast } from "@app/hooks/useToast";
|
||||||
import { formatAxiosError } from "@app/lib/api";
|
import { formatAxiosError } from "@app/lib/api";
|
||||||
import { getUserDisplayName } from "@app/lib/getUserDisplayName";
|
import { getUserDisplayName } from "@app/lib/getUserDisplayName";
|
||||||
import { Laptop, LogOut, Moon, Sun, Smartphone, Trash2 } from "lucide-react";
|
import { Check, Laptop, Moon, Sun, Trash2 } from "lucide-react";
|
||||||
import { useTheme } from "next-themes";
|
import { useTheme } from "next-themes";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
@@ -149,42 +152,49 @@ export default function ProfileIcon() {
|
|||||||
>
|
>
|
||||||
<span>{t("changePassword")}</span>
|
<span>{t("changePassword")}</span>
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
<DropdownMenuSeparator />
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<DropdownMenuItem onClick={() => setOpenViewDevices(true)}>
|
<DropdownMenuItem onClick={() => setOpenViewDevices(true)}>
|
||||||
<Smartphone className="mr-2 h-4 w-4" />
|
|
||||||
<span>{t("viewDevices") || "View Devices"}</span>
|
<span>{t("viewDevices") || "View Devices"}</span>
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
<DropdownMenuSeparator />
|
<DropdownMenuSeparator />
|
||||||
<DropdownMenuLabel>{t("theme")}</DropdownMenuLabel>
|
<DropdownMenuLabel>{t("theme")}</DropdownMenuLabel>
|
||||||
{(["light", "dark", "system"] as const).map(
|
<DropdownMenuSub>
|
||||||
(themeOption) => (
|
<DropdownMenuSubTrigger className="[&_svg:not([class*='text-'])]:text-muted-foreground">
|
||||||
<DropdownMenuItem
|
{userTheme === "light" && (
|
||||||
key={themeOption}
|
<Sun className="mr-2 h-4 w-4" />
|
||||||
onClick={() => handleThemeChange(themeOption)}
|
)}
|
||||||
>
|
{userTheme === "dark" && (
|
||||||
{themeOption === "light" && (
|
<Moon className="mr-2 h-4 w-4" />
|
||||||
<Sun className="mr-2 h-4 w-4" />
|
)}
|
||||||
)}
|
{userTheme === "system" && (
|
||||||
{themeOption === "dark" && (
|
<Laptop className="mr-2 h-4 w-4" />
|
||||||
<Moon className="mr-2 h-4 w-4" />
|
)}
|
||||||
)}
|
<span className="capitalize">{t(userTheme)}</span>
|
||||||
{themeOption === "system" && (
|
</DropdownMenuSubTrigger>
|
||||||
<Laptop className="mr-2 h-4 w-4" />
|
<DropdownMenuSubContent className="min-w-[8rem]">
|
||||||
)}
|
{(["light", "dark", "system"] as const).map(
|
||||||
<span className="capitalize">
|
(themeOption) => (
|
||||||
{t(themeOption)}
|
<DropdownMenuItem
|
||||||
</span>
|
key={themeOption}
|
||||||
{userTheme === themeOption && (
|
onClick={() =>
|
||||||
<span className="absolute right-2 flex h-3.5 w-3.5 items-center justify-center">
|
handleThemeChange(themeOption)
|
||||||
<span className="h-2 w-2 rounded-full bg-primary"></span>
|
}
|
||||||
</span>
|
className="flex items-center gap-2"
|
||||||
)}
|
>
|
||||||
</DropdownMenuItem>
|
{userTheme === themeOption && (
|
||||||
)
|
<Check className="h-4 w-4" />
|
||||||
)}
|
)}
|
||||||
|
<span className="capitalize">
|
||||||
|
{t(themeOption)}
|
||||||
|
</span>
|
||||||
|
</DropdownMenuItem>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</DropdownMenuSubContent>
|
||||||
|
</DropdownMenuSub>
|
||||||
<DropdownMenuSeparator />
|
<DropdownMenuSeparator />
|
||||||
|
<DropdownMenuLabel>{t("language")}</DropdownMenuLabel>
|
||||||
<LocaleSwitcher />
|
<LocaleSwitcher />
|
||||||
<DropdownMenuSeparator />
|
<DropdownMenuSeparator />
|
||||||
{user?.type === UserType.Internal && !user?.serverAdmin && (
|
{user?.type === UserType.Internal && !user?.serverAdmin && (
|
||||||
|
|||||||
Reference in New Issue
Block a user