Merge branch 'fix/license-invite-refresh' into e-300

pull/19898/head
NFish 12 months ago
commit 0bd509cb75

@ -25,6 +25,7 @@ import { useAppContext } from '@/context/app-context'
import Loading from '@/app/components/base/loading' import Loading from '@/app/components/base/loading'
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints' import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
import type { App } from '@/types/app' import type { App } from '@/types/app'
import useDocumentTitle from '@/hooks/use-document-title'
export type IAppDetailLayoutProps = { export type IAppDetailLayoutProps = {
children: React.ReactNode children: React.ReactNode
@ -94,9 +95,10 @@ const AppDetailLayout: FC<IAppDetailLayoutProps> = (props) => {
return navs return navs
}, []) }, [])
useDocumentTitle(appDetail?.name || t('common.menus.appDetail'))
useEffect(() => { useEffect(() => {
if (appDetail) { if (appDetail) {
document.title = `${(appDetail.name || 'App')} - Dify`
const localeMode = localStorage.getItem('app-detail-collapse-or-expand') || 'expand' const localeMode = localStorage.getItem('app-detail-collapse-or-expand') || 'expand'
const mode = isMobile ? 'collapse' : 'expand' const mode = isMobile ? 'collapse' : 'expand'
setAppSiderbarExpand(isMobile ? mode : localeMode) setAppSiderbarExpand(isMobile ? mode : localeMode)

@ -29,6 +29,7 @@ import { useStore as useTagStore } from '@/app/components/base/tag-management/st
import TagManagementModal from '@/app/components/base/tag-management' import TagManagementModal from '@/app/components/base/tag-management'
import TagFilter from '@/app/components/base/tag-management/filter' import TagFilter from '@/app/components/base/tag-management/filter'
import CheckboxWithLabel from '@/app/components/datasets/create/website/base/checkbox-with-label' import CheckboxWithLabel from '@/app/components/datasets/create/website/base/checkbox-with-label'
import useDocumentTitle from '@/hooks/use-document-title'
const getKey = ( const getKey = (
pageIndex: number, pageIndex: number,
@ -96,7 +97,6 @@ const Apps = () => {
] ]
useEffect(() => { useEffect(() => {
document.title = `${t('common.menus.apps')} - Dify`
if (localStorage.getItem(NEED_REFRESH_APP_LIST_KEY) === '1') { if (localStorage.getItem(NEED_REFRESH_APP_LIST_KEY) === '1') {
localStorage.removeItem(NEED_REFRESH_APP_LIST_KEY) localStorage.removeItem(NEED_REFRESH_APP_LIST_KEY)
mutate() mutate()
@ -128,6 +128,8 @@ const Apps = () => {
return () => observer?.disconnect() return () => observer?.disconnect()
}, [isLoading, setSize, anchorRef, mutate, data, error]) }, [isLoading, setSize, anchorRef, mutate, data, error])
useDocumentTitle(isLoading ? '' : t('common.menus.apps'))
const { run: handleSearch } = useDebounceFn(() => { const { run: handleSearch } = useDebounceFn(() => {
setSearchKeywords(keywords) setSearchKeywords(keywords)
}, { wait: 500 }) }, { wait: 500 })

@ -6,13 +6,11 @@ import style from '../list.module.css'
import Apps from './Apps' import Apps from './Apps'
import { useEducationInit } from '@/app/education-apply/hooks' import { useEducationInit } from '@/app/education-apply/hooks'
import { useGlobalPublicStore } from '@/context/global-public-context' import { useGlobalPublicStore } from '@/context/global-public-context'
import useDocumentTitle from '@/hooks/use-document-title'
const AppList = () => { const AppList = () => {
const { t } = useTranslation() const { t } = useTranslation()
useEducationInit() useEducationInit()
const { systemFeatures } = useGlobalPublicStore() const { systemFeatures } = useGlobalPublicStore()
useDocumentTitle(t('common.menus.apps'))
return ( return (
<div className='relative flex h-0 shrink-0 grow flex-col overflow-y-auto bg-background-body'> <div className='relative flex h-0 shrink-0 grow flex-col overflow-y-auto bg-background-body'>
<Apps /> <Apps />

@ -31,6 +31,7 @@ import { getLocaleOnClient } from '@/i18n'
import { useAppContext } from '@/context/app-context' import { useAppContext } from '@/context/app-context'
import Tooltip from '@/app/components/base/tooltip' import Tooltip from '@/app/components/base/tooltip'
import LinkedAppsPanel from '@/app/components/base/linked-apps-panel' import LinkedAppsPanel from '@/app/components/base/linked-apps-panel'
import useDocumentTitle from '@/hooks/use-document-title'
export type IAppDetailLayoutProps = { export type IAppDetailLayoutProps = {
children: React.ReactNode children: React.ReactNode
@ -158,10 +159,7 @@ const DatasetDetailLayout: FC<IAppDetailLayoutProps> = (props) => {
return baseNavigation return baseNavigation
}, [datasetRes?.provider, datasetId, t]) }, [datasetRes?.provider, datasetId, t])
useEffect(() => { useDocumentTitle(datasetRes?.name || t('common.menus.datasets'))
if (datasetRes)
document.title = `${datasetRes.name || 'Dataset'} - Dify`
}, [datasetRes])
const setAppSiderbarExpand = useStore(state => state.setAppSiderbarExpand) const setAppSiderbarExpand = useStore(state => state.setAppSiderbarExpand)

@ -30,6 +30,7 @@ import { useStore as useTagStore } from '@/app/components/base/tag-management/st
import { useAppContext } from '@/context/app-context' import { useAppContext } from '@/context/app-context'
import { useExternalApiPanel } from '@/context/external-api-panel-context' import { useExternalApiPanel } from '@/context/external-api-panel-context'
import { useGlobalPublicStore } from '@/context/global-public-context' import { useGlobalPublicStore } from '@/context/global-public-context'
import useDocumentTitle from '@/hooks/use-document-title'
const Container = () => { const Container = () => {
const { t } = useTranslation() const { t } = useTranslation()
@ -39,8 +40,7 @@ const Container = () => {
const showTagManagementModal = useTagStore(s => s.showTagManagementModal) const showTagManagementModal = useTagStore(s => s.showTagManagementModal)
const { showExternalApiPanel, setShowExternalApiPanel } = useExternalApiPanel() const { showExternalApiPanel, setShowExternalApiPanel } = useExternalApiPanel()
const [includeAll, { toggle: toggleIncludeAll }] = useBoolean(false) const [includeAll, { toggle: toggleIncludeAll }] = useBoolean(false)
useDocumentTitle(t('dataset.knowledge'))
document.title = `${t('dataset.knowledge')} - Dify`
const options = useMemo(() => { const options = useMemo(() => {
return [ return [

@ -60,7 +60,6 @@ const Datasets = ({
useEffect(() => { useEffect(() => {
loadingStateRef.current = isLoading loadingStateRef.current = isLoading
document.title = `${t('dataset.knowledge')} - Dify`
}, [isLoading, t]) }, [isLoading, t])
const onScroll = useCallback( const onScroll = useCallback(

@ -20,6 +20,7 @@ import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
import { checkOrSetAccessToken } from '@/app/components/share/utils' import { checkOrSetAccessToken } from '@/app/components/share/utils'
import AppUnavailable from '@/app/components/base/app-unavailable' import AppUnavailable from '@/app/components/base/app-unavailable'
import cn from '@/utils/classnames' import cn from '@/utils/classnames'
import useDocumentTitle from '@/hooks/use-document-title'
type ChatWithHistoryProps = { type ChatWithHistoryProps = {
className?: string className?: string
@ -46,14 +47,10 @@ const ChatWithHistory: FC<ChatWithHistoryProps> = ({
useEffect(() => { useEffect(() => {
themeBuilder?.buildTheme(site?.chat_color_theme, site?.chat_color_theme_inverted) themeBuilder?.buildTheme(site?.chat_color_theme, site?.chat_color_theme_inverted)
if (site) {
if (customConfig)
document.title = `${site.title}`
else
document.title = `${site.title} - Powered by Dify`
}
}, [site, customConfig, themeBuilder]) }, [site, customConfig, themeBuilder])
useDocumentTitle(site?.title || 'Chat')
if (appInfoLoading) { if (appInfoLoading) {
return ( return (
<Loading type='app' /> <Loading type='app' />

@ -21,6 +21,7 @@ import Header from '@/app/components/base/chat/embedded-chatbot/header'
import ChatWrapper from '@/app/components/base/chat/embedded-chatbot/chat-wrapper' import ChatWrapper from '@/app/components/base/chat/embedded-chatbot/chat-wrapper'
import LogoSite from '@/app/components/base/logo/logo-site' import LogoSite from '@/app/components/base/logo/logo-site'
import cn from '@/utils/classnames' import cn from '@/utils/classnames'
import useDocumentTitle from '@/hooks/use-document-title'
const Chatbot = () => { const Chatbot = () => {
const { const {
@ -44,14 +45,10 @@ const Chatbot = () => {
useEffect(() => { useEffect(() => {
themeBuilder?.buildTheme(site?.chat_color_theme, site?.chat_color_theme_inverted) themeBuilder?.buildTheme(site?.chat_color_theme, site?.chat_color_theme_inverted)
if (site) {
if (customConfig)
document.title = `${site.title}`
else
document.title = `${site.title} - Powered by Dify`
}
}, [site, customConfig, themeBuilder]) }, [site, customConfig, themeBuilder])
useDocumentTitle(site?.title || 'Chat')
if (appInfoLoading) { if (appInfoLoading) {
return ( return (
<> <>

@ -8,6 +8,7 @@ import { useAppContext } from '@/context/app-context'
import { fetchMembers } from '@/service/common' import { fetchMembers } from '@/service/common'
import type { InstalledApp } from '@/models/explore' import type { InstalledApp } from '@/models/explore'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import useDocumentTitle from '@/hooks/use-document-title'
export type IExploreProps = { export type IExploreProps = {
children: React.ReactNode children: React.ReactNode
@ -23,8 +24,9 @@ const Explore: FC<IExploreProps> = ({
const [installedApps, setInstalledApps] = useState<InstalledApp[]>([]) const [installedApps, setInstalledApps] = useState<InstalledApp[]>([])
const { t } = useTranslation() const { t } = useTranslation()
useDocumentTitle(t('common.menus.explore'))
useEffect(() => { useEffect(() => {
document.title = `${t('explore.title')} - Dify`;
(async () => { (async () => {
const { accounts } = await fetchMembers({ url: '/workspaces/current/members', params: {} }) const { accounts } = await fetchMembers({ url: '/workspaces/current/members', params: {} })
if (!accounts) if (!accounts)

@ -32,6 +32,7 @@ const InviteModal = ({
}: IInviteModalProps) => { }: IInviteModalProps) => {
const { t } = useTranslation() const { t } = useTranslation()
const licenseLimit = useProviderContextSelector(s => s.licenseLimit) const licenseLimit = useProviderContextSelector(s => s.licenseLimit)
const refreshLicenseLimit = useProviderContextSelector(s => s.refreshLicenseLimit)
const [emails, setEmails] = useState<string[]>([]) const [emails, setEmails] = useState<string[]>([])
const { notify } = useContext(ToastContext) const { notify } = useContext(ToastContext)
const [isLimited, setIsLimited] = useState(false) const [isLimited, setIsLimited] = useState(false)
@ -59,6 +60,7 @@ const InviteModal = ({
}) })
if (result === 'success') { if (result === 'success') {
refreshLicenseLimit()
onCancel() onCancel()
onSend(invitation_results) onSend(invitation_results)
} }

@ -42,6 +42,7 @@ import { noop } from 'lodash-es'
import { PLUGIN_TYPE_SEARCH_MAP } from '../marketplace/plugin-type-switch' import { PLUGIN_TYPE_SEARCH_MAP } from '../marketplace/plugin-type-switch'
import { PLUGIN_PAGE_TABS_MAP } from '../hooks' import { PLUGIN_PAGE_TABS_MAP } from '../hooks'
import { useGlobalPublicStore } from '@/context/global-public-context' import { useGlobalPublicStore } from '@/context/global-public-context'
import useDocumentTitle from '@/hooks/use-document-title'
const PACKAGE_IDS_KEY = 'package-ids' const PACKAGE_IDS_KEY = 'package-ids'
const BUNDLE_INFO_KEY = 'bundle-info' const BUNDLE_INFO_KEY = 'bundle-info'
@ -58,8 +59,7 @@ const PluginPage = ({
const { locale } = useContext(I18n) const { locale } = useContext(I18n)
const searchParams = useSearchParams() const searchParams = useSearchParams()
const { replace } = useRouter() const { replace } = useRouter()
useDocumentTitle(t('plugin.metadata.title'))
document.title = `${t('plugin.metadata.title')} - Dify`
// just support install one package now // just support install one package now
const packageId = useMemo(() => { const packageId = useMemo(() => {

@ -42,6 +42,7 @@ import cn from '@/utils/classnames'
import { useGetAppAccessMode, useGetUserCanAccessApp } from '@/service/access-control' import { useGetAppAccessMode, useGetUserCanAccessApp } from '@/service/access-control'
import { AccessMode } from '@/models/access-control' import { AccessMode } from '@/models/access-control'
import { useGlobalPublicStore } from '@/context/global-public-context' import { useGlobalPublicStore } from '@/context/global-public-context'
import useDocumentTitle from '@/hooks/use-document-title'
const GROUP_SIZE = 5 // to avoid RPM(Request per minute) limit. The group task finished then the next group. const GROUP_SIZE = 5 // to avoid RPM(Request per minute) limit. The group task finished then the next group.
enum TaskStatus { enum TaskStatus {
@ -105,7 +106,6 @@ const TextGeneration: FC<IMainProps> = ({
const systemFeatures = useGlobalPublicStore(s => s.systemFeatures) const systemFeatures = useGlobalPublicStore(s => s.systemFeatures)
const [appId, setAppId] = useState<string>('') const [appId, setAppId] = useState<string>('')
const [siteInfo, setSiteInfo] = useState<SiteInfo | null>(null) const [siteInfo, setSiteInfo] = useState<SiteInfo | null>(null)
const [canReplaceLogo, setCanReplaceLogo] = useState<boolean>(false)
const [customConfig, setCustomConfig] = useState<Record<string, any> | null>(null) const [customConfig, setCustomConfig] = useState<Record<string, any> | null>(null)
const [promptConfig, setPromptConfig] = useState<PromptConfig | null>(null) const [promptConfig, setPromptConfig] = useState<PromptConfig | null>(null)
const [moreLikeThisConfig, setMoreLikeThisConfig] = useState<MoreLikeThisConfig | null>(null) const [moreLikeThisConfig, setMoreLikeThisConfig] = useState<MoreLikeThisConfig | null>(null)
@ -411,10 +411,9 @@ const TextGeneration: FC<IMainProps> = ({
useEffect(() => { useEffect(() => {
(async () => { (async () => {
const [appData, appParams]: any = await fetchInitData() const [appData, appParams]: any = await fetchInitData()
const { app_id: appId, site: siteInfo, can_replace_logo, custom_config } = appData const { app_id: appId, site: siteInfo, custom_config } = appData
setAppId(appId) setAppId(appId)
setSiteInfo(siteInfo as SiteInfo) setSiteInfo(siteInfo as SiteInfo)
setCanReplaceLogo(can_replace_logo)
setCustomConfig(custom_config) setCustomConfig(custom_config)
changeLanguage(siteInfo.default_language) changeLanguage(siteInfo.default_language)
@ -435,17 +434,10 @@ const TextGeneration: FC<IMainProps> = ({
setMoreLikeThisConfig(more_like_this) setMoreLikeThisConfig(more_like_this)
setTextToSpeechConfig(text_to_speech) setTextToSpeechConfig(text_to_speech)
})() })()
}, []) }, [fetchInitData])
// Can Use metadata(https://beta.nextjs.org/docs/api-reference/metadata) to set title. But it only works in server side client. // Can Use metadata(https://beta.nextjs.org/docs/api-reference/metadata) to set title. But it only works in server side client.
useEffect(() => { useDocumentTitle(siteInfo?.title || t('share.generation.title'))
if (siteInfo?.title) {
if (canReplaceLogo)
document.title = `${siteInfo.title}`
else
document.title = `${siteInfo.title} - Powered by Dify`
}
}, [siteInfo?.title, canReplaceLogo])
useAppFavicon({ useAppFavicon({
enable: !isInstalledApp, enable: !isInstalledApp,

@ -54,7 +54,8 @@ type ProviderContextState = {
size: number size: number
limit: number limit: number
} }
} },
refreshLicenseLimit: () => void
} }
const ProviderContext = createContext<ProviderContextState>({ const ProviderContext = createContext<ProviderContextState>({
modelProviders: [], modelProviders: [],
@ -95,6 +96,7 @@ const ProviderContext = createContext<ProviderContextState>({
limit: 0, limit: 0,
}, },
}, },
refreshLicenseLimit: noop,
}) })
export const useProviderContext = () => useContext(ProviderContext) export const useProviderContext = () => useContext(ProviderContext)
@ -223,6 +225,7 @@ export const ProviderContextProvider = ({
isEducationAccount: isEducationAccount?.result || false, isEducationAccount: isEducationAccount?.result || false,
webappCopyrightEnabled, webappCopyrightEnabled,
licenseLimit, licenseLimit,
refreshLicenseLimit: fetchPlan,
}}> }}>
{children} {children}
</ProviderContext.Provider> </ProviderContext.Provider>

@ -1,19 +1,10 @@
'use client' 'use client'
import { useLayoutEffect } from 'react'
import { useGlobalPublicStore } from '@/context/global-public-context' import { useGlobalPublicStore } from '@/context/global-public-context'
import { useFavicon, useTitle } from 'ahooks'
export default function useDocumentTitle(title: string) { export default function useDocumentTitle(title: string) {
const { systemFeatures } = useGlobalPublicStore() const systemFeatures = useGlobalPublicStore(s => s.systemFeatures)
useLayoutEffect(() => { const prefix = title ? `${title} - ` : ''
const prefix = title ? `${title} - ` : '' useTitle(systemFeatures.branding.enabled ? `${prefix}${systemFeatures.branding.application_title}` : `${prefix}Dify`)
if (systemFeatures.branding.enabled) { useFavicon(systemFeatures.branding.enabled ? systemFeatures.branding.favicon : '/favicon.ico')
document.title = `${prefix}${systemFeatures.branding.application_title}`
const faviconEle = document.querySelector('link[rel*=\'icon\']') as HTMLLinkElement
if (faviconEle)
faviconEle.href = systemFeatures.branding.favicon
}
else {
document.title = `${prefix}Dify`
}
}, [systemFeatures, title])
} }

Loading…
Cancel
Save