mirror of
https://github.com/langgenius/dify.git
synced 2026-05-13 08:57:28 +08:00
Merge branch 'main' into refactor/migrate-app-detail-to-tanstack-query
This commit is contained in:
commit
e71ebc19e6
@ -1,10 +1,9 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import type { InvitationResult } from '@/models/common'
|
import type { InvitationResult } from '@/models/common'
|
||||||
import { RiPencilLine, RiUserAddLine } from '@remixicon/react'
|
import { RiPencilLine } from '@remixicon/react'
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import Avatar from '@/app/components/base/avatar'
|
import Avatar from '@/app/components/base/avatar'
|
||||||
import Button from '@/app/components/base/button'
|
|
||||||
import Tooltip from '@/app/components/base/tooltip'
|
import Tooltip from '@/app/components/base/tooltip'
|
||||||
import { NUM_INFINITE } from '@/app/components/billing/config'
|
import { NUM_INFINITE } from '@/app/components/billing/config'
|
||||||
import { Plan } from '@/app/components/billing/type'
|
import { Plan } from '@/app/components/billing/type'
|
||||||
@ -16,8 +15,8 @@ import { useProviderContext } from '@/context/provider-context'
|
|||||||
import { useFormatTimeFromNow } from '@/hooks/use-format-time-from-now'
|
import { useFormatTimeFromNow } from '@/hooks/use-format-time-from-now'
|
||||||
import { LanguagesSupported } from '@/i18n-config/language'
|
import { LanguagesSupported } from '@/i18n-config/language'
|
||||||
import { useMembers } from '@/service/use-common'
|
import { useMembers } from '@/service/use-common'
|
||||||
import { cn } from '@/utils/classnames'
|
|
||||||
import EditWorkspaceModal from './edit-workspace-modal'
|
import EditWorkspaceModal from './edit-workspace-modal'
|
||||||
|
import InviteButton from './invite-button'
|
||||||
import InviteModal from './invite-modal'
|
import InviteModal from './invite-modal'
|
||||||
import InvitedModal from './invited-modal'
|
import InvitedModal from './invited-modal'
|
||||||
import Operation from './operation'
|
import Operation from './operation'
|
||||||
@ -37,7 +36,7 @@ const MembersPage = () => {
|
|||||||
|
|
||||||
const { userProfile, currentWorkspace, isCurrentWorkspaceOwner, isCurrentWorkspaceManager } = useAppContext()
|
const { userProfile, currentWorkspace, isCurrentWorkspaceOwner, isCurrentWorkspaceManager } = useAppContext()
|
||||||
const { data, refetch } = useMembers()
|
const { data, refetch } = useMembers()
|
||||||
const { systemFeatures } = useGlobalPublicStore()
|
const systemFeatures = useGlobalPublicStore(s => s.systemFeatures)
|
||||||
const { formatTimeFromNow } = useFormatTimeFromNow()
|
const { formatTimeFromNow } = useFormatTimeFromNow()
|
||||||
const [inviteModalVisible, setInviteModalVisible] = useState(false)
|
const [inviteModalVisible, setInviteModalVisible] = useState(false)
|
||||||
const [invitationResults, setInvitationResults] = useState<InvitationResult[]>([])
|
const [invitationResults, setInvitationResults] = useState<InvitationResult[]>([])
|
||||||
@ -104,10 +103,9 @@ const MembersPage = () => {
|
|||||||
{isMemberFull && (
|
{isMemberFull && (
|
||||||
<UpgradeBtn className="mr-2" loc="member-invite" />
|
<UpgradeBtn className="mr-2" loc="member-invite" />
|
||||||
)}
|
)}
|
||||||
<Button variant="primary" className={cn('shrink-0')} disabled={!isCurrentWorkspaceManager || isMemberFull} onClick={() => setInviteModalVisible(true)}>
|
<div className="shrink-0">
|
||||||
<RiUserAddLine className="mr-1 h-4 w-4" />
|
<InviteButton disabled={!isCurrentWorkspaceManager || isMemberFull} onClick={() => setInviteModalVisible(true)} />
|
||||||
{t('members.invite', { ns: 'common' })}
|
</div>
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="overflow-visible lg:overflow-visible">
|
<div className="overflow-visible lg:overflow-visible">
|
||||||
<div className="flex min-w-[480px] items-center border-b border-divider-regular py-[7px]">
|
<div className="flex min-w-[480px] items-center border-b border-divider-regular py-[7px]">
|
||||||
|
|||||||
@ -0,0 +1,34 @@
|
|||||||
|
import { RiUserAddLine } from '@remixicon/react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import Button from '@/app/components/base/button'
|
||||||
|
import Loading from '@/app/components/base/loading'
|
||||||
|
import { useAppContext } from '@/context/app-context'
|
||||||
|
import { useGlobalPublicStore } from '@/context/global-public-context'
|
||||||
|
import { useWorkspacePermissions } from '@/service/use-workspace'
|
||||||
|
|
||||||
|
type InviteButtonProps = {
|
||||||
|
disabled?: boolean
|
||||||
|
onClick?: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const InviteButton = (props: InviteButtonProps) => {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
const { currentWorkspace } = useAppContext()
|
||||||
|
const systemFeatures = useGlobalPublicStore(s => s.systemFeatures)
|
||||||
|
const { data: workspacePermissions, isFetching: isFetchingWorkspacePermissions } = useWorkspacePermissions(currentWorkspace!.id, systemFeatures.branding.enabled)
|
||||||
|
if (systemFeatures.branding.enabled) {
|
||||||
|
if (isFetchingWorkspacePermissions) {
|
||||||
|
return <Loading />
|
||||||
|
}
|
||||||
|
if (!workspacePermissions || workspacePermissions.allow_member_invite !== true) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Button variant="primary" {...props}>
|
||||||
|
<RiUserAddLine className="mr-1 h-4 w-4" />
|
||||||
|
{t('members.invite', { ns: 'common' })}
|
||||||
|
</Button>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default InviteButton
|
||||||
@ -5,6 +5,10 @@ import {
|
|||||||
} from '@remixicon/react'
|
} from '@remixicon/react'
|
||||||
import { Fragment } from 'react'
|
import { Fragment } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import Loading from '@/app/components/base/loading'
|
||||||
|
import { useAppContext } from '@/context/app-context'
|
||||||
|
import { useGlobalPublicStore } from '@/context/global-public-context'
|
||||||
|
import { useWorkspacePermissions } from '@/service/use-workspace'
|
||||||
import { cn } from '@/utils/classnames'
|
import { cn } from '@/utils/classnames'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@ -13,6 +17,17 @@ type Props = {
|
|||||||
|
|
||||||
const TransferOwnership = ({ onOperate }: Props) => {
|
const TransferOwnership = ({ onOperate }: Props) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
const { currentWorkspace } = useAppContext()
|
||||||
|
const systemFeatures = useGlobalPublicStore(s => s.systemFeatures)
|
||||||
|
const { data: workspacePermissions, isFetching: isFetchingWorkspacePermissions } = useWorkspacePermissions(currentWorkspace!.id, systemFeatures.branding.enabled)
|
||||||
|
if (systemFeatures.branding.enabled) {
|
||||||
|
if (isFetchingWorkspacePermissions) {
|
||||||
|
return <Loading />
|
||||||
|
}
|
||||||
|
if (!workspacePermissions || workspacePermissions.allow_owner_transfer !== true) {
|
||||||
|
return <span className="system-sm-regular px-3 text-text-secondary">{t('members.owner', { ns: 'common' })}</span>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Menu as="div" className="relative h-full w-full">
|
<Menu as="div" className="relative h-full w-full">
|
||||||
|
|||||||
17
web/service/use-workspace.ts
Normal file
17
web/service/use-workspace.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import type { ICurrentWorkspace } from '@/models/common'
|
||||||
|
import { useQuery } from '@tanstack/react-query'
|
||||||
|
import { get } from './base'
|
||||||
|
|
||||||
|
type WorkspacePermissions = {
|
||||||
|
workspace_id: ICurrentWorkspace['id']
|
||||||
|
allow_member_invite: boolean
|
||||||
|
allow_owner_transfer: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useWorkspacePermissions(workspaceId: ICurrentWorkspace['id'], enabled: boolean) {
|
||||||
|
return useQuery({
|
||||||
|
queryKey: ['workspace-permissions', workspaceId],
|
||||||
|
queryFn: () => get<WorkspacePermissions>('/workspaces/current/permission'),
|
||||||
|
enabled: enabled && !!workspaceId,
|
||||||
|
})
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user