mirror of
http://112.124.100.131/huang.ze/ebiz-dify-ai.git
synced 2025-12-10 03:16:51 +08:00
Revert "feat: knowledge admin role" (#6018)
This commit is contained in:
@@ -35,7 +35,6 @@ import CustomPage from '@/app/components/custom/custom-page'
|
||||
import Modal from '@/app/components/base/modal'
|
||||
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
|
||||
import { useProviderContext } from '@/context/provider-context'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
|
||||
const iconClassName = `
|
||||
w-4 h-4 ml-3 mr-2
|
||||
@@ -65,11 +64,8 @@ export default function AccountSetting({
|
||||
const [activeMenu, setActiveMenu] = useState(activeTab)
|
||||
const { t } = useTranslation()
|
||||
const { enableBilling, enableReplaceWebAppLogo } = useProviderContext()
|
||||
const { isCurrentWorkspaceDatasetOperator } = useAppContext()
|
||||
|
||||
const workplaceGroupItems = (() => {
|
||||
if (isCurrentWorkspaceDatasetOperator)
|
||||
return []
|
||||
return [
|
||||
{
|
||||
key: 'provider',
|
||||
@@ -176,9 +172,7 @@ export default function AccountSetting({
|
||||
{
|
||||
menuItems.map(menuItem => (
|
||||
<div key={menuItem.key} className='mb-4'>
|
||||
{!isCurrentWorkspaceDatasetOperator && (
|
||||
<div className='px-2 mb-[6px] text-[10px] sm:text-xs font-medium text-gray-500'>{menuItem.name}</div>
|
||||
)}
|
||||
<div className='px-2 mb-[6px] text-[10px] sm:text-xs font-medium text-gray-500'>{menuItem.name}</div>
|
||||
<div>
|
||||
{
|
||||
menuItem.items.map(item => (
|
||||
|
||||
@@ -29,7 +29,6 @@ const MembersPage = () => {
|
||||
owner: t('common.members.owner'),
|
||||
admin: t('common.members.admin'),
|
||||
editor: t('common.members.editor'),
|
||||
dataset_operator: t('common.members.datasetOperator'),
|
||||
normal: t('common.members.normal'),
|
||||
}
|
||||
const { locale } = useContext(I18n)
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
'use client'
|
||||
import { useCallback, useState } from 'react'
|
||||
import { Fragment, useCallback, useMemo, useState } from 'react'
|
||||
import { useContext } from 'use-context-selector'
|
||||
import { XMarkIcon } from '@heroicons/react/24/outline'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { ReactMultiEmail } from 'react-multi-email'
|
||||
import { Listbox, Transition } from '@headlessui/react'
|
||||
import { CheckIcon } from '@heroicons/react/20/solid'
|
||||
import cn from 'classnames'
|
||||
import s from './index.module.css'
|
||||
import RoleSelector from './role-selector'
|
||||
import Modal from '@/app/components/base/modal'
|
||||
import Button from '@/app/components/base/button'
|
||||
import { inviteMember } from '@/service/common'
|
||||
@@ -30,14 +31,29 @@ const InviteModal = ({
|
||||
const { notify } = useContext(ToastContext)
|
||||
|
||||
const { locale } = useContext(I18n)
|
||||
const [role, setRole] = useState<string>('normal')
|
||||
|
||||
const InvitingRoles = useMemo(() => [
|
||||
{
|
||||
name: 'normal',
|
||||
description: t('common.members.normalTip'),
|
||||
},
|
||||
{
|
||||
name: 'editor',
|
||||
description: t('common.members.editorTip'),
|
||||
},
|
||||
{
|
||||
name: 'admin',
|
||||
description: t('common.members.adminTip'),
|
||||
},
|
||||
], [t])
|
||||
const [role, setRole] = useState(InvitingRoles[0])
|
||||
|
||||
const handleSend = useCallback(async () => {
|
||||
if (emails.map((email: string) => emailRegex.test(email)).every(Boolean)) {
|
||||
try {
|
||||
const { result, invitation_results } = await inviteMember({
|
||||
url: '/workspaces/current/members/invite-email',
|
||||
body: { emails, role, language: locale },
|
||||
body: { emails, role: role.name, language: locale },
|
||||
})
|
||||
|
||||
if (result === 'success') {
|
||||
@@ -83,9 +99,53 @@ const InviteModal = ({
|
||||
placeholder={t('common.members.emailPlaceholder') || ''}
|
||||
/>
|
||||
</div>
|
||||
<div className='mb-6'>
|
||||
<RoleSelector value={role} onChange={setRole} />
|
||||
</div>
|
||||
<Listbox value={role} onChange={setRole}>
|
||||
<div className="relative pb-6">
|
||||
<Listbox.Button className="relative w-full py-2 pl-3 pr-10 text-left bg-gray-100 outline-none border-none appearance-none text-sm text-gray-900 rounded-lg">
|
||||
<span className="block truncate capitalize">{t('common.members.invitedAsRole', { role: t(`common.members.${role.name}`) })}</span>
|
||||
</Listbox.Button>
|
||||
<Transition
|
||||
as={Fragment}
|
||||
leave="transition ease-in duration-200"
|
||||
leaveFrom="opacity-200"
|
||||
leaveTo="opacity-0"
|
||||
>
|
||||
<Listbox.Options className="absolute w-full py-1 my-2 overflow-auto text-base bg-white rounded-md shadow-lg max-h-60 ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm">
|
||||
{InvitingRoles.map(role =>
|
||||
<Listbox.Option
|
||||
key={role.name}
|
||||
className={({ active }) =>
|
||||
`${active ? ' bg-gray-50 rounded-xl' : ' bg-transparent'}
|
||||
cursor-default select-none relative py-2 px-4 mx-2 flex flex-col`
|
||||
}
|
||||
value={role}
|
||||
>
|
||||
{({ selected }) => (
|
||||
<div className='flex flex-row'>
|
||||
<span
|
||||
className={cn(
|
||||
'text-indigo-600 mr-2',
|
||||
'flex items-center',
|
||||
)}
|
||||
>
|
||||
{selected && (<CheckIcon className="h-5 w-5" aria-hidden="true" />)}
|
||||
</span>
|
||||
<div className=' flex flex-col flex-grow'>
|
||||
<span className={`${selected ? 'font-medium' : 'font-normal'} capitalize block truncate`}>
|
||||
{t(`common.members.${role.name}`)}
|
||||
</span>
|
||||
<span className={`${selected ? 'font-medium' : 'font-normal'} capitalize block text-gray-500`}>
|
||||
{role.description}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</Listbox.Option>,
|
||||
)}
|
||||
</Listbox.Options>
|
||||
</Transition>
|
||||
</div>
|
||||
</Listbox>
|
||||
<Button
|
||||
tabIndex={0}
|
||||
className='w-full'
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import cn from 'classnames'
|
||||
import React, { useState } from 'react'
|
||||
import { RiArrowDownSLine } from '@remixicon/react'
|
||||
import { useProviderContext } from '@/context/provider-context'
|
||||
import {
|
||||
PortalToFollowElem,
|
||||
PortalToFollowElemContent,
|
||||
PortalToFollowElemTrigger,
|
||||
} from '@/app/components/base/portal-to-follow-elem'
|
||||
import { Check } from '@/app/components/base/icons/src/vender/line/general'
|
||||
|
||||
export type RoleSelectorProps = {
|
||||
value: string
|
||||
onChange: (role: string) => void
|
||||
}
|
||||
|
||||
const RoleSelector = ({ value, onChange }: RoleSelectorProps) => {
|
||||
const { t } = useTranslation()
|
||||
const [open, setOpen] = useState(false)
|
||||
const { datasetOperatorEnabled } = useProviderContext()
|
||||
|
||||
const toHump = (name: string) => name.replace(/_(\w)/g, (all, letter) => letter.toUpperCase())
|
||||
|
||||
return (
|
||||
<PortalToFollowElem
|
||||
open={open}
|
||||
onOpenChange={setOpen}
|
||||
placement='bottom-start'
|
||||
offset={4}
|
||||
>
|
||||
<div className='relative'>
|
||||
<PortalToFollowElemTrigger
|
||||
onClick={() => setOpen(v => !v)}
|
||||
className='block'
|
||||
>
|
||||
<div className={cn('flex items-center px-3 py-2 rounded-lg bg-gray-100 cursor-pointer hover:bg-gray-200', open && 'bg-gray-200')}>
|
||||
<div className='grow mr-2 text-gray-900 text-sm leading-5'>{t('common.members.invitedAsRole', { role: t(`common.members.${toHump(value)}`) })}</div>
|
||||
<RiArrowDownSLine className='shrink-0 w-4 h-4 text-gray-700' />
|
||||
</div>
|
||||
</PortalToFollowElemTrigger>
|
||||
<PortalToFollowElemContent className='z-[1002]'>
|
||||
<div className='relative w-[336px] bg-white rounded-lg border-[0.5px] bg-gray-200 shadow-lg'>
|
||||
<div className='p-1'>
|
||||
<div className='p-2 rounded-lg hover:bg-gray-50 cursor-pointer' onClick={() => {
|
||||
onChange('normal')
|
||||
setOpen(false)
|
||||
}}>
|
||||
<div className='relative pl-5'>
|
||||
<div className='text-gray-700 text-sm leading-5'>{t('common.members.normal')}</div>
|
||||
<div className='text-gray-500 text-xs leading-[18px]'>{t('common.members.normalTip')}</div>
|
||||
{value === 'normal' && <Check className='absolute top-0.5 left-0 w-4 h-4 text-primary-600'/>}
|
||||
</div>
|
||||
</div>
|
||||
<div className='p-2 rounded-lg hover:bg-gray-50 cursor-pointer' onClick={() => {
|
||||
onChange('editor')
|
||||
setOpen(false)
|
||||
}}>
|
||||
<div className='relative pl-5'>
|
||||
<div className='text-gray-700 text-sm leading-5'>{t('common.members.editor')}</div>
|
||||
<div className='text-gray-500 text-xs leading-[18px]'>{t('common.members.editorTip')}</div>
|
||||
{value === 'editor' && <Check className='absolute top-0.5 left-0 w-4 h-4 text-primary-600'/>}
|
||||
</div>
|
||||
</div>
|
||||
<div className='p-2 rounded-lg hover:bg-gray-50 cursor-pointer' onClick={() => {
|
||||
onChange('admin')
|
||||
setOpen(false)
|
||||
}}>
|
||||
<div className='relative pl-5'>
|
||||
<div className='text-gray-700 text-sm leading-5'>{t('common.members.admin')}</div>
|
||||
<div className='text-gray-500 text-xs leading-[18px]'>{t('common.members.adminTip')}</div>
|
||||
{value === 'admin' && <Check className='absolute top-0.5 left-0 w-4 h-4 text-primary-600'/>}
|
||||
</div>
|
||||
</div>
|
||||
{datasetOperatorEnabled && (
|
||||
<div className='p-2 rounded-lg hover:bg-gray-50 cursor-pointer' onClick={() => {
|
||||
onChange('dataset_operator')
|
||||
setOpen(false)
|
||||
}}>
|
||||
<div className='relative pl-5'>
|
||||
<div className='text-gray-700 text-sm leading-5'>{t('common.members.datasetOperator')}</div>
|
||||
<div className='text-gray-500 text-xs leading-[18px]'>{t('common.members.datasetOperatorTip')}</div>
|
||||
{value === 'dataset_operator' && <Check className='absolute top-0.5 left-0 w-4 h-4 text-primary-600'/>}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</PortalToFollowElemContent>
|
||||
</div>
|
||||
</PortalToFollowElem>
|
||||
)
|
||||
}
|
||||
|
||||
export default RoleSelector
|
||||
@@ -1,12 +1,11 @@
|
||||
'use client'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Fragment, useMemo } from 'react'
|
||||
import { Fragment } from 'react'
|
||||
import { useContext } from 'use-context-selector'
|
||||
import { Menu, Transition } from '@headlessui/react'
|
||||
import cn from 'classnames'
|
||||
import { CheckIcon, ChevronDownIcon } from '@heroicons/react/24/outline'
|
||||
import s from './index.module.css'
|
||||
import { useProviderContext } from '@/context/provider-context'
|
||||
import type { Member } from '@/models/common'
|
||||
import { deleteMemberOrCancelInvitation, updateMemberRole } from '@/service/common'
|
||||
import { ToastContext } from '@/app/components/base/toast'
|
||||
@@ -34,22 +33,13 @@ const Operation = ({
|
||||
onOperate,
|
||||
}: IOperationProps) => {
|
||||
const { t } = useTranslation()
|
||||
const { datasetOperatorEnabled } = useProviderContext()
|
||||
const RoleMap = {
|
||||
owner: t('common.members.owner'),
|
||||
admin: t('common.members.admin'),
|
||||
editor: t('common.members.editor'),
|
||||
normal: t('common.members.normal'),
|
||||
dataset_operator: t('common.members.datasetOperator'),
|
||||
}
|
||||
const roleList = useMemo(() => {
|
||||
return [
|
||||
...['admin', 'editor', 'normal'],
|
||||
...(datasetOperatorEnabled ? ['dataset_operator'] : []),
|
||||
]
|
||||
}, [datasetOperatorEnabled])
|
||||
const { notify } = useContext(ToastContext)
|
||||
const toHump = (name: string) => name.replace(/_(\w)/g, (all, letter) => letter.toUpperCase())
|
||||
const handleDeleteMemberOrCancelInvitation = async () => {
|
||||
try {
|
||||
await deleteMemberOrCancelInvitation({ url: `/workspaces/current/members/${member.id}` })
|
||||
@@ -109,7 +99,7 @@ const Operation = ({
|
||||
>
|
||||
<div className="px-1 py-1">
|
||||
{
|
||||
roleList.map(role => (
|
||||
['admin', 'editor', 'normal'].map(role => (
|
||||
<Menu.Item key={role}>
|
||||
<div className={itemClassName} onClick={() => handleUpdateMemberRole(role)}>
|
||||
{
|
||||
@@ -118,8 +108,8 @@ const Operation = ({
|
||||
: <div className={itemIconClassName} />
|
||||
}
|
||||
<div>
|
||||
<div className={itemTitleClassName}>{t(`common.members.${toHump(role)}`)}</div>
|
||||
<div className={itemDescClassName}>{t(`common.members.${toHump(role)}Tip`)}</div>
|
||||
<div className={itemTitleClassName}>{t(`common.members.${role}`)}</div>
|
||||
<div className={itemDescClassName}>{t(`common.members.${role}Tip`)}</div>
|
||||
</div>
|
||||
</div>
|
||||
</Menu.Item>
|
||||
|
||||
Reference in New Issue
Block a user