import React, { useState } from 'react'; import { AccessRoleIds, ResourceType } from 'librechat-data-provider'; import { Share2Icon, Users, Loader, Shield, Link, CopyCheck } from 'lucide-react'; import { Button, OGDialog, OGDialogTitle, OGDialogClose, OGDialogContent, OGDialogTrigger, useToastContext, } from '@librechat/client'; import type { TPrincipal } from 'librechat-data-provider'; import { usePeoplePickerPermissions, useResourcePermissionState, useCopyToClipboard, useLocalize, } from '~/hooks'; import GenericManagePermissionsDialog from './GenericManagePermissionsDialog'; import PublicSharingToggle from './PublicSharingToggle'; import AccessRolesPicker from './AccessRolesPicker'; import { cn, removeFocusOutlines } from '~/utils'; import { PeoplePicker } from './PeoplePicker'; export default function GenericGrantAccessDialog({ resourceName, resourceDbId, resourceId, resourceType, onGrantAccess, disabled = false, children, }: { resourceDbId?: string | null; resourceId?: string | null; resourceName?: string; resourceType: ResourceType; onGrantAccess?: (shares: TPrincipal[], isPublic: boolean, publicRole: AccessRoleIds) => void; disabled?: boolean; children?: React.ReactNode; }) { const localize = useLocalize(); const { showToast } = useToastContext(); const [isModalOpen, setIsModalOpen] = useState(false); const [isCopying, setIsCopying] = useState(false); // Use shared hooks const { hasPeoplePickerAccess, peoplePickerTypeFilter } = usePeoplePickerPermissions(); const { config, updatePermissionsMutation, currentShares, currentIsPublic, currentPublicRole, isPublic, setIsPublic, publicRole, setPublicRole, } = useResourcePermissionState(resourceType, resourceDbId, isModalOpen); const [newShares, setNewShares] = useState([]); const [defaultPermissionId, setDefaultPermissionId] = useState( config?.defaultViewerRoleId, ); const resourceUrl = config?.getResourceUrl ? config?.getResourceUrl(resourceId || '') : ''; const copyResourceUrl = useCopyToClipboard({ text: resourceUrl }); if (!resourceDbId) { return null; } if (!config) { console.error(`Unsupported resource type: ${resourceType}`); return null; } const handleGrantAccess = async () => { try { const sharesToAdd = newShares.map((share) => ({ ...share, accessRoleId: defaultPermissionId, })); const allShares = [...currentShares, ...sharesToAdd]; await updatePermissionsMutation.mutateAsync({ resourceType, resourceId: resourceDbId, data: { updated: sharesToAdd, removed: [], public: isPublic, publicAccessRoleId: isPublic ? publicRole : undefined, }, }); if (onGrantAccess) { onGrantAccess(allShares, isPublic, publicRole); } showToast({ message: `Access granted successfully to ${newShares.length} ${newShares.length === 1 ? 'person' : 'people'}${isPublic ? ' and made public' : ''}`, status: 'success', }); setNewShares([]); setDefaultPermissionId(config?.defaultViewerRoleId); setIsPublic(false); setPublicRole(config?.defaultViewerRoleId); setIsModalOpen(false); } catch (error) { console.error('Error granting access:', error); showToast({ message: 'Failed to grant access. Please try again.', status: 'error', }); } }; const handleCancel = () => { setNewShares([]); setDefaultPermissionId(config?.defaultViewerRoleId); setIsPublic(false); setPublicRole(config?.defaultViewerRoleId); setIsModalOpen(false); }; const totalCurrentShares = currentShares.length + (currentIsPublic ? 1 : 0); const submitButtonActive = newShares.length > 0 || isPublic !== currentIsPublic || publicRole !== currentPublicRole; const TriggerComponent = children ? ( children ) : ( ); return ( {TriggerComponent}
{localize('com_ui_share_var', { 0: config?.getShareMessage(resourceName), })}
{hasPeoplePickerAccess && ( <>
)}
{hasPeoplePickerAccess && ( )} {resourceId && resourceUrl && ( )}
); }