mirror of
https://github.com/blakeblackshear/frigate.git
synced 2025-12-06 13:34:13 +03:00
* Translation module init
* Add more i18n keys
* fix: fix string wrong
* refactor: use namespace translation file
* chore: add more translation key
* fix: fix some page name error
* refactor: change Trans tag for t function
* chore: fix some key not work
* chore: fix SearchFilterDialog i18n key error
Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com>
* chore: fix en i18n file filter missing some keys
* chore: add some i18n keys
* chore: add more i18n keys again
* feat: add search page i18n
* feat: add explore model i18n keys
* Update web/src/components/menu/GeneralSettings.tsx
Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com>
* Update web/src/components/menu/GeneralSettings.tsx
Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com>
* Update web/src/components/menu/GeneralSettings.tsx
Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com>
* feat: add more live i18n keys
* feat: add more search setting i18n keys
* fix: remove some comment
* fix: fix some setting page url error
* Update web/src/views/settings/SearchSettingsView.tsx
Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com>
* fix: add system missing keys
* fix: update password update i18n keys
* chore: remove outdate translation.json file
* fix: fix exploreSettings error
* chore: add object setting i18n keys
* Update web/src/views/recording/RecordingView.tsx
Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com>
* Update web/public/locales/en/components/filter.json
Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com>
* Update web/src/components/overlay/ExportDialog.tsx
Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com>
* feat: add more i18n keys
* fix: fix motionDetectionTuner html node
* feat: add more page i18n keys
* fix: cameraStream i18n keys error
* feat: add Player i18n keys
* feat: add more toast i18n keys
* feat: change explore setting name
* feat: add more document title i18n keys
* feat: add more search i18n keys
* fix: fix accessDenied i18n keys error
* chore: add objectType i18n
* chore: add inputWithTags i18n
* chore: add SearchFilterDialog i18n
* Update web/src/views/settings/ObjectSettingsView.tsx
Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com>
* Update web/src/views/settings/ObjectSettingsView.tsx
Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com>
* Update web/src/views/settings/ObjectSettingsView.tsx
Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com>
* Update web/src/views/settings/ObjectSettingsView.tsx
Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com>
* Update web/src/views/settings/ObjectSettingsView.tsx
Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com>
* chore: add some missing i18n keys
* chore: remove most import { t } from "i18next";
---------
Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com>
149 lines
4.9 KiB
TypeScript
149 lines
4.9 KiB
TypeScript
import {
|
|
Tooltip,
|
|
TooltipContent,
|
|
TooltipTrigger,
|
|
} from "@/components/ui/tooltip";
|
|
import { baseUrl } from "../../api/baseUrl";
|
|
import { cn } from "@/lib/utils";
|
|
import { TooltipPortal } from "@radix-ui/react-tooltip";
|
|
import { isDesktop } from "react-device-detect";
|
|
import { VscAccount } from "react-icons/vsc";
|
|
import {
|
|
DropdownMenu,
|
|
DropdownMenuContent,
|
|
DropdownMenuItem,
|
|
DropdownMenuLabel,
|
|
DropdownMenuSeparator,
|
|
DropdownMenuTrigger,
|
|
} from "../ui/dropdown-menu";
|
|
import { Drawer, DrawerContent, DrawerTrigger } from "../ui/drawer";
|
|
import { DialogClose } from "../ui/dialog";
|
|
import { LuLogOut, LuSquarePen } from "react-icons/lu";
|
|
import useSWR from "swr";
|
|
|
|
import { useState } from "react";
|
|
import axios from "axios";
|
|
import { toast } from "sonner";
|
|
import SetPasswordDialog from "../overlay/SetPasswordDialog";
|
|
import { useTranslation } from "react-i18next";
|
|
|
|
type AccountSettingsProps = {
|
|
className?: string;
|
|
};
|
|
|
|
export default function AccountSettings({ className }: AccountSettingsProps) {
|
|
const { t } = useTranslation(["views/settings"]);
|
|
const { data: profile } = useSWR("profile");
|
|
const { data: config } = useSWR("config");
|
|
const logoutUrl = config?.proxy?.logout_url || `${baseUrl}api/logout`;
|
|
|
|
const [passwordDialogOpen, setPasswordDialogOpen] = useState(false);
|
|
|
|
const Container = isDesktop ? DropdownMenu : Drawer;
|
|
const Trigger = isDesktop ? DropdownMenuTrigger : DrawerTrigger;
|
|
const Content = isDesktop ? DropdownMenuContent : DrawerContent;
|
|
const MenuItem = isDesktop ? DropdownMenuItem : DialogClose;
|
|
|
|
const handlePasswordSave = async (password: string) => {
|
|
if (!profile?.username || profile.username === "anonymous") return;
|
|
axios
|
|
.put(`users/${profile.username}/password`, { password })
|
|
.then((response) => {
|
|
if (response.status === 200) {
|
|
setPasswordDialogOpen(false);
|
|
toast.success(t("users.toast.success.updatePassword"), {
|
|
position: "top-center",
|
|
});
|
|
}
|
|
})
|
|
.catch((error) => {
|
|
const errorMessage =
|
|
error.response?.data?.message ||
|
|
error.response?.data?.detail ||
|
|
"Unknown error";
|
|
toast.error(
|
|
t("users.toast.error.setPasswordFailed", {
|
|
errorMessage,
|
|
}),
|
|
{
|
|
position: "top-center",
|
|
},
|
|
);
|
|
});
|
|
};
|
|
|
|
return (
|
|
<Container modal={!isDesktop}>
|
|
<Trigger>
|
|
<Tooltip>
|
|
<TooltipTrigger asChild>
|
|
<div
|
|
className={cn(
|
|
"flex flex-col items-center justify-center",
|
|
isDesktop
|
|
? "cursor-pointer rounded-lg bg-secondary text-secondary-foreground hover:bg-muted"
|
|
: "text-secondary-foreground",
|
|
className,
|
|
)}
|
|
>
|
|
<VscAccount className="size-5 md:m-[6px]" />
|
|
</div>
|
|
</TooltipTrigger>
|
|
<TooltipPortal>
|
|
<TooltipContent side="right">
|
|
<p>{t("menu.user.account", { ns: "common" })}</p>
|
|
</TooltipContent>
|
|
</TooltipPortal>
|
|
</Tooltip>
|
|
</Trigger>
|
|
<Content
|
|
className={
|
|
isDesktop ? "mr-5 w-72" : "max-h-[75dvh] overflow-hidden p-2"
|
|
}
|
|
>
|
|
<div className="scrollbar-container w-full flex-col overflow-y-auto overflow-x-hidden">
|
|
<DropdownMenuLabel>
|
|
{t("menu.user.current", {
|
|
ns: "common",
|
|
user:
|
|
profile?.username || t("menu.user.anonymous", { ns: "common" }),
|
|
})}{" "}
|
|
{t("role." + profile?.role) &&
|
|
`(${t("role." + profile?.role, { ns: "common" })})`}
|
|
</DropdownMenuLabel>
|
|
<DropdownMenuSeparator className={isDesktop ? "mt-3" : "mt-1"} />
|
|
{profile?.username && profile.username !== "anonymous" && (
|
|
<MenuItem
|
|
className={
|
|
isDesktop ? "cursor-pointer" : "flex items-center p-2 text-sm"
|
|
}
|
|
aria-label={t("menu.user.setPassword", { ns: "common" })}
|
|
onClick={() => setPasswordDialogOpen(true)}
|
|
>
|
|
<LuSquarePen className="mr-2 size-4" />
|
|
<span>{t("menu.user.setPassword", { ns: "common" })}</span>
|
|
</MenuItem>
|
|
)}
|
|
<MenuItem
|
|
className={
|
|
isDesktop ? "cursor-pointer" : "flex items-center p-2 text-sm"
|
|
}
|
|
aria-label={t("menu.user.logout", { ns: "common" })}
|
|
>
|
|
<a className="flex" href={logoutUrl}>
|
|
<LuLogOut className="mr-2 size-4" />
|
|
<span>{t("menu.user.logout", { ns: "common" })}</span>
|
|
</a>
|
|
</MenuItem>
|
|
</div>
|
|
</Content>
|
|
<SetPasswordDialog
|
|
show={passwordDialogOpen}
|
|
onSave={handlePasswordSave}
|
|
onCancel={() => setPasswordDialogOpen(false)}
|
|
username={profile?.username}
|
|
/>
|
|
</Container>
|
|
);
|
|
}
|