/** * This file is part of the NocoBase (R) project. * Copyright (c) 2020-2024 NocoBase Co., Ltd. * Authors: NocoBase Team. * * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License. * For more information, please refer to: https://www.nocobase.com/agreement. */ import { UserOutlined } from '@ant-design/icons'; import { css } from '@emotion/css'; import { error } from '@nocobase/utils/client'; import { App, Dropdown, Menu, MenuProps } from 'antd'; import React, { createContext, useCallback, useMemo as useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useACLRoleContext, useAPIClient, useCurrentUserContext, useToken } from '..'; import { useNavigateNoUpdate } from '../application/CustomRouterContextProvider'; import { useChangePassword } from './ChangePassword'; import { useCurrentUserSettingsMenu } from './CurrentUserSettingsMenuProvider'; import { useEditProfile } from './EditProfile'; import { useLanguageSettings } from './LanguageSettings'; import { useSwitchRole } from './SwitchRole'; const useNickname = () => { const { data } = useCurrentUserContext(); const { token } = useToken(); return useEffect(() => { return { key: 'nickname', disabled: true, label: ( {data?.data?.nickname || data?.data?.username || data?.data?.email} ), }; }, [data?.data?.email, data?.data?.nickname, data?.data?.username, data?.data.version, token.colorTextDescription]); }; /** * @note If you want to change here, Note the Setting block on the mobile side */ export const SettingsMenu: React.FC<{ redirectUrl?: string; }> = (props) => { const { addMenuItem, getMenuItems } = useCurrentUserSettingsMenu(); const { redirectUrl = '' } = props; const { allowAll, snippets } = useACLRoleContext(); const appAllowed = allowAll || snippets?.includes('app'); const navigate = useNavigateNoUpdate(); const api = useAPIClient(); const { t } = useTranslation(); const silenceApi = useAPIClient(); const check = useCallback(async () => { return await new Promise((resolve) => { const heartbeat = setInterval(() => { silenceApi .silent() .resource('app') .getInfo() .then((res) => { if (res?.status === 200) { resolve('ok'); clearInterval(heartbeat); } return res; }) .catch((err) => { error(err); }); }, 3000); }); }, [silenceApi]); const nickname = useNickname(); const editProfile = useEditProfile(); const changePassword = useChangePassword(); const switchRole = useSwitchRole(); const languageSettings = useLanguageSettings(); const { modal } = App.useApp(); const controlApp = useEffect(() => { if (!appAllowed) { return []; } return [ { key: 'cache', label: t('Clear cache'), onClick: async () => { await api.resource('app').clearCache(); window.location.reload(); }, }, { key: 'reboot', label: t('Restart application'), onClick: async () => { modal.confirm({ title: t('Restart application'), // content: t('The will interrupt service, it may take a few seconds to restart. Are you sure to continue?'), okText: t('Restart'), okButtonProps: { danger: true, }, onOk: async () => { await api.resource('app').restart(); }, }); }, }, { key: 'divider_4', type: 'divider', }, ]; }, [api, appAllowed, check, modal, t]); useEffect(() => { const items = [ nickname, { key: 'divider_1', type: 'divider', }, editProfile, changePassword, { key: 'divider_2', type: 'divider', }, switchRole, { key: 'divider_3', type: 'divider', }, ...controlApp, { key: 'signout', label: t('Sign out'), onClick: async () => { const { data } = await api.auth.signOut(); if (data?.data?.redirect) { window.location.href = data.data.redirect; } else { navigate(`/signin?redirect=${encodeURIComponent(redirectUrl)}`); } }, }, ]; items.forEach((item) => { if (item) { addMenuItem(item); } }); if (languageSettings) { addMenuItem(languageSettings, { before: 'divider_3' }); } }, [ addMenuItem, api.auth, changePassword, controlApp, editProfile, languageSettings, navigate, redirectUrl, switchRole, t, nickname, ]); return ; }; export const DropdownVisibleContext = createContext(null); DropdownVisibleContext.displayName = 'DropdownVisibleContext'; export const CurrentUser = () => { const [visible, setVisible] = useState(false); const { token } = useToken(); return (
{ setVisible(visible); }} dropdownRender={() => { return ; }} >
); };