import type { Credential } from '../types' import { Button } from '@langgenius/dify-ui/button' import { cn } from '@langgenius/dify-ui/cn' import { StatusDot } from '@langgenius/dify-ui/status-dot' import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip' import { RiInformationLine } from '@remixicon/react' import { useAtomValue } from 'jotai' import { memo, useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' import ActionButton from '@/app/components/base/action-button' import Badge from '@/app/components/base/badge' import Input from '@/app/components/base/input' import { userProfileIdAtom } from '@/context/account-state' import { useCredentialPermissions } from '@/hooks/use-credential-permissions' import { CredentialTypeEnum } from '../types' type ItemProps = { credential: Credential onDelete?: (id: string) => void onEdit?: (id: string, values: Record) => void onSetDefault?: (id: string) => void onRename?: (payload: { credential_id: string; name: string }) => void disableRename?: boolean disableEdit?: boolean disableDelete?: boolean disableSetDefault?: boolean onItemClick?: (id: string) => void showSelectedIcon?: boolean selectedCredentialId?: string disabled?: boolean } const Item = ({ credential, onDelete, onEdit, onSetDefault, onRename, disableRename, disableEdit, disableDelete, disableSetDefault, onItemClick, showSelectedIcon, selectedCredentialId, disabled, }: ItemProps) => { const { t } = useTranslation() const [renaming, setRenaming] = useState(false) const [renameValue, setRenameValue] = useState(credential.name) const { canUseCredential, canManageCredential } = useCredentialPermissions() const isOAuth = credential.credential_type === CredentialTypeEnum.OAUTH2 const isPersonal = credential.visibility === 'only_me' const currentUserId = useAtomValue(userProfileIdAtom) // Borrowed-from-teammate: the backend explicitly flagged this row as another member's // only_me credential, returned only because the current node still references it. // Fallback heuristic (created_by mismatch on a selected row) is kept for backends // that don't yet emit the flag. const isSelected = showSelectedIcon && selectedCredentialId === credential.id const isConfiguredByOther = !!credential.created_by && !!currentUserId && credential.created_by !== currentUserId const isBorrowed = !!credential.from_other_member || (isSelected && isConfiguredByOther && isPersonal) const showSwitchAwayHint = isBorrowed const showAction = useMemo(() => { return !(disableRename && disableEdit && disableDelete && disableSetDefault) }, [disableRename, disableEdit, disableDelete, disableSetDefault]) const CredentialItem = (
{ if (disabled || credential.not_allowed_to_use || !canUseCredential) return onItemClick?.(credential.id === '__workspace_default__' ? '' : credential.id) }} > {renaming && (
setRenameValue(e.target.value)} placeholder={t(($) => $['placeholder.input'], { ns: 'common' })} onClick={(e) => e.stopPropagation()} />
)} {!renaming && (
{showSelectedIcon && (
{selectedCredentialId === credential.id && ( )}
)}
{credential.name}
{credential.is_default && ( {t(($) => $['auth.default'], { ns: 'plugin' })} )}
)} {showSwitchAwayHint && (
} /> {t(($) => $['auth.onlyAtCreationHintTooltip'], { ns: 'plugin' })} )} {!showSwitchAwayHint && credential.from_enterprise && ( {t(($) => $['auth.enterprise'], { ns: 'plugin' })} )} {showAction && !renaming && (
{!credential.is_default && !disableSetDefault && !credential.not_allowed_to_use && !isBorrowed && ( )} {!disableRename && !credential.from_enterprise && !credential.not_allowed_to_use && !isBorrowed && ( { e.stopPropagation() setRenaming(true) setRenameValue(credential.name) }} > } /> {t(($) => $['operation.rename'], { ns: 'common' })} )} {!isOAuth && !disableEdit && !credential.from_enterprise && !credential.not_allowed_to_use && !isBorrowed && ( { e.stopPropagation() onEdit?.(credential.id, { ...credential.credentials, __name__: credential.name, __credential_id__: credential.id, }) }} > } /> {t(($) => $['operation.edit'], { ns: 'common' })} )} {!disableDelete && !credential.from_enterprise && !isBorrowed && ( { e.stopPropagation() onDelete?.(credential.id) }} > } /> {t(($) => $['operation.delete'], { ns: 'common' })} )}
)} ) if (credential.not_allowed_to_use) { return ( {t(($) => $['auth.customCredentialUnavailable'], { ns: 'plugin' })} ) } return CredentialItem } export default memo(Item)