import { useTranslation } from 'react-i18next' import cn from 'classnames' import React, { useCallback, useMemo, useState } from 'react' import { useDebounceFn } from 'ahooks' import { RiArrowDownSLine, RiGroup2Line, RiLock2Line } from '@remixicon/react' import { PortalToFollowElem, PortalToFollowElemContent, PortalToFollowElemTrigger, } from '@/app/components/base/portal-to-follow-elem' import Avatar from '@/app/components/base/avatar' import Input from '@/app/components/base/input' import { DatasetPermission } from '@/models/datasets' import { useSelector as useAppContextWithSelector } from '@/context/app-context' import type { Member } from '@/models/common' import Item from './permission-item' import MemberItem from './member-item' export type RoleSelectorProps = { disabled?: boolean permission?: DatasetPermission value: string[] memberList: Member[] onChange: (permission?: DatasetPermission) => void onMemberSelect: (v: string[]) => void } const PermissionSelector = ({ disabled, permission, value, memberList, onChange, onMemberSelect, }: RoleSelectorProps) => { const { t } = useTranslation() const userProfile = useAppContextWithSelector(state => state.userProfile) const [open, setOpen] = useState(false) const [keywords, setKeywords] = useState('') const [searchKeywords, setSearchKeywords] = useState('') const { run: handleSearch } = useDebounceFn(() => { setSearchKeywords(keywords) }, { wait: 500 }) const handleKeywordsChange = (value: string) => { setKeywords(value) handleSearch() } const selectMember = useCallback((member: Member) => { if (value.includes(member.id)) onMemberSelect(value.filter(v => v !== member.id)) else onMemberSelect([...value, member.id]) }, [value, onMemberSelect]) const selectedMembers = useMemo(() => { return [ userProfile, ...memberList.filter(member => member.id !== userProfile.id).filter(member => value.includes(member.id)), ] }, [userProfile, value, memberList]) const showMe = useMemo(() => { return userProfile.name.includes(searchKeywords) || userProfile.email.includes(searchKeywords) }, [searchKeywords, userProfile]) const filteredMemberList = useMemo(() => { return memberList.filter(member => (member.name.includes(searchKeywords) || member.email.includes(searchKeywords)) && member.id !== userProfile.id && ['owner', 'admin', 'editor', 'dataset_operator'].includes(member.role)) }, [memberList, searchKeywords, userProfile]) const onSelectOnlyMe = useCallback(() => { onChange(DatasetPermission.onlyMe) setOpen(false) }, [onChange]) const onSelectAllMembers = useCallback(() => { onChange(DatasetPermission.allTeamMembers) setOpen(false) }, [onChange]) const onSelectPartialMembers = useCallback(() => { onChange(DatasetPermission.partialMembers) onMemberSelect([userProfile.id]) }, [onChange, onMemberSelect, userProfile]) const isOnlyMe = permission === DatasetPermission.onlyMe const isAllTeamMembers = permission === DatasetPermission.allTeamMembers const isPartialMembers = permission === DatasetPermission.partialMembers const selectedMemberNames = selectedMembers.map(member => member.name).join(', ') return (
!disabled && setOpen(v => !v)} className='block' >
{ isOnlyMe && ( <>
{t('datasetSettings.form.permissionsOnlyMe')}
) } { isAllTeamMembers && ( <>
{t('datasetSettings.form.permissionsAllMember')}
) } { isPartialMembers && ( <>
{ selectedMembers.length === 1 && ( ) } { selectedMembers.length >= 2 && ( <> ) }
{selectedMemberNames}
) }
{/* Only me */} } text={t('datasetSettings.form.permissionsOnlyMe')} onClick={onSelectOnlyMe} isSelected={isOnlyMe} /> {/* All team members */}
} text={t('datasetSettings.form.permissionsAllMember')} onClick={onSelectAllMembers} isSelected={isAllTeamMembers} /> {/* Partial members */}
} text={t('datasetSettings.form.permissionsInvitedMembers')} onClick={onSelectPartialMembers} isSelected={isPartialMembers} />
{isPartialMembers && (
handleKeywordsChange(e.target.value)} onClear={() => handleKeywordsChange('')} />
{showMe && ( } name={userProfile.name} email={userProfile.email} isSelected isMe /> )} {filteredMemberList.map(member => ( } name={member.name} email={member.email} isSelected={value.includes(member.id)} onClick={selectMember.bind(null, member)} /> ))} { !showMe && filteredMemberList.length === 0 && (
{t('datasetSettings.form.onSearchResults')}
) }
)}
) } export default PermissionSelector