NODEDC_TASKMANAGER/plane-src/apps/admin/app/(all)/(dashboard)/sidebar-dropdown.tsx

155 lines
5.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Copyright (c) 2023-present Plane Software, Inc. and contributors
* SPDX-License-Identifier: AGPL-3.0-only
* See the LICENSE file for details.
*/
import { Fragment, useEffect, useState } from "react";
import { observer } from "mobx-react";
import { useTheme as useNextTheme } from "next-themes";
import { LogOut, UserCog2, Palette } from "lucide-react";
import { Menu, Transition } from "@headlessui/react";
// plane internal packages
import { API_BASE_URL } from "@plane/constants";
import { AuthService } from "@plane/services";
import { Avatar } from "@plane/ui";
import { getFileURL, cn } from "@plane/utils";
// hooks
import { useTheme, useUser } from "@/hooks/store";
// service initialization
const authService = new AuthService();
export const AdminSidebarDropdown = observer(function AdminSidebarDropdown() {
// store hooks
const { isSidebarCollapsed } = useTheme();
const { currentUser, signOut } = useUser();
// hooks
const { resolvedTheme, setTheme } = useNextTheme();
// state
const [csrfToken, setCsrfToken] = useState<string | undefined>(undefined);
const handleThemeSwitch = () => {
const newTheme = resolvedTheme === "dark" ? "light" : "dark";
setTheme(newTheme);
};
const handleSignOut = () => signOut();
const getSidebarMenuItems = (align: "left" | "right" = "left") => (
<Menu.Items
className={cn(
"nodedc-glass-popup-surface absolute z-20 mt-1.5 flex w-56 flex-col divide-y divide-white/6 px-2 py-2 text-11 outline-none",
{
"left-0": align === "left",
"right-0": align === "right",
"left-4": isSidebarCollapsed,
}
)}
>
<div className="flex flex-col gap-2.5 pb-2">
<span className="truncate px-2 text-secondary">{currentUser?.email}</span>
</div>
<div className="py-2">
<Menu.Item
as="button"
type="button"
className="nodedc-settings-sidebar-item flex w-full items-center gap-2 px-2 py-1 text-left"
onClick={handleThemeSwitch}
>
<Palette className="h-4 w-4 stroke-[1.5]" />
{resolvedTheme === "dark" ? "Светлая тема" : "Темная тема"}
</Menu.Item>
</div>
<div className="py-2">
<form method="POST" action={`${API_BASE_URL}/api/instances/admins/sign-out/`} onSubmit={handleSignOut}>
<input type="hidden" name="csrfmiddlewaretoken" value={csrfToken} />
<Menu.Item
as="button"
type="submit"
className="nodedc-settings-sidebar-item flex w-full items-center gap-2 px-2 py-1 text-left"
>
<LogOut className="h-4 w-4 stroke-[1.5]" />
Выйти
</Menu.Item>
</form>
</div>
</Menu.Items>
);
useEffect(() => {
if (csrfToken === undefined)
void authService.requestCSRFToken().then((data) => data?.csrf_token && setCsrfToken(data.csrf_token));
}, [csrfToken]);
return (
<div className="px-3 pt-4 pb-2">
<div className="h-full w-full truncate">
<div
className={`nodedc-admin-sidebar-profile flex flex-grow items-center gap-x-3 truncate px-3 py-3 ${
isSidebarCollapsed ? "justify-center" : ""
}`}
>
<Menu as="div" className="flex-shrink-0">
<Menu.Button
className={cn("grid place-items-center outline-none", {
"cursor-default": !isSidebarCollapsed,
})}
>
<div className="nodedc-admin-sidebar-avatar-button flex size-10 flex-shrink-0 items-center justify-center">
<UserCog2 className="size-5 text-[rgb(var(--nodedc-card-active-rgb))]" />
</div>
</Menu.Button>
{isSidebarCollapsed && (
<Transition
as={Fragment}
enter="transition ease-out duration-100"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition ease-in duration-75"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
{getSidebarMenuItems()}
</Transition>
)}
</Menu>
{!isSidebarCollapsed && (
<div className="min-w-0 flex-1">
<h4 className="truncate text-15 font-medium text-primary">Глобальный админ</h4>
<div className="truncate text-11 font-medium text-tertiary">Супер-администратор</div>
</div>
)}
{!isSidebarCollapsed && currentUser && (
<Menu as="div" className="relative flex-shrink-0">
<Menu.Button className="nodedc-admin-sidebar-action grid size-8 place-items-center outline-none">
<Avatar
name={currentUser.display_name}
src={getFileURL(currentUser.avatar_url)}
size={24}
shape="square"
className="!text-body-sm-medium"
/>
</Menu.Button>
<Transition
as={Fragment}
enter="transition ease-out duration-100"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition ease-in duration-75"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
{getSidebarMenuItems("right")}
</Transition>
</Menu>
)}
</div>
</div>
</div>
);
});