Download frontend/src/components/workspace/OwnerCell.jsx from Seth0330/qualifier: direct link, hf CLI and curl.
- Browser
- Download file 3.22 kB
-
https://huggingface.co/spaces/Seth0330/qualifier/resolve/main/frontend/src/components/workspace/OwnerCell.jsx
- Command line
-
hf download hf://spaces/Seth0330/qualifier/frontend/src/components/workspace/OwnerCell.jsx
-
curl -L -o OwnerCell.jsx https://huggingface.co/spaces/Seth0330/qualifier/resolve/main/frontend/src/components/workspace/OwnerCell.jsx
3.22 kB
| import React from 'react'; | |
| import { Select, SelectTrigger, SelectContent, SelectItem } from '@/components/ui/select'; | |
| import { cn } from '@/lib/utils'; | |
| import { OwnerAvatarCircle, ownerDisplayLabel } from '@/lib/ownerAvatar'; | |
| const EMPTY_OWNER_KEY = '__owner_none__'; | |
| const MEMBER_TAKE_OWNERSHIP_VALUE = '__member_take_ownership__'; | |
| /** | |
| * Owner avatar + reassignment dropdown, shared across Leads/Contacts/Companies. Admins can | |
| * assign to anyone or unassign; members can only self-claim an unassigned row (same rules the | |
| * backend enforces on the owner_user_id patch). | |
| */ | |
| export default function OwnerCell({ row, isAdmin, tenantMembers, currentUserId, onChangeOwner }) { | |
| const trigger = ( | |
| <SelectTrigger | |
| className={cn( | |
| 'h-9 w-9 shrink-0 p-0 justify-center border-slate-200 shadow-none', | |
| '[&>svg]:hidden' | |
| )} | |
| title={isAdmin ? 'Change owner' : ownerDisplayLabel(row)} | |
| aria-label={`Owner: ${ownerDisplayLabel(row)}. Open menu ${isAdmin ? 'to change' : 'for details'}.`} | |
| > | |
| <OwnerAvatarCircle userId={row.owner_user_id} initials={row.owner_initials} /> | |
| </SelectTrigger> | |
| ); | |
| const header = ( | |
| <div role="presentation" className="pointer-events-none border-b border-slate-100 px-2 py-2 mb-1"> | |
| <div className="flex items-center gap-2"> | |
| <OwnerAvatarCircle userId={row.owner_user_id} initials={row.owner_initials} /> | |
| <div className="min-w-0 flex-1"> | |
| <div className="truncate text-sm font-semibold text-slate-900"> | |
| {ownerDisplayLabel(row)} | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| ); | |
| const currentValue = | |
| row.owner_user_id != null && row.owner_user_id !== '' ? String(row.owner_user_id) : EMPTY_OWNER_KEY; | |
| if (isAdmin) { | |
| return ( | |
| <Select | |
| value={currentValue} | |
| onValueChange={(v) => onChangeOwner(v === EMPTY_OWNER_KEY ? null : Number(v))} | |
| > | |
| {trigger} | |
| <SelectContent className="min-w-[12rem]"> | |
| {header} | |
| <SelectItem value={EMPTY_OWNER_KEY}>Unassigned</SelectItem> | |
| {(tenantMembers || []).map((m) => ( | |
| <SelectItem key={m.user_id} value={String(m.user_id)}> | |
| {(m.name || m.email || `User ${m.user_id}`).trim()} | |
| </SelectItem> | |
| ))} | |
| </SelectContent> | |
| </Select> | |
| ); | |
| } | |
| return ( | |
| <Select | |
| value={currentValue} | |
| onValueChange={(v) => { | |
| if (v === MEMBER_TAKE_OWNERSHIP_VALUE) onChangeOwner(currentUserId); | |
| }} | |
| > | |
| {trigger} | |
| <SelectContent className="min-w-[12rem]"> | |
| {header} | |
| {currentUserId != null && (row.owner_user_id == null || row.owner_user_id === '') ? ( | |
| <SelectItem value={MEMBER_TAKE_OWNERSHIP_VALUE}>Take ownership</SelectItem> | |
| ) : null} | |
| </SelectContent> | |
| </Select> | |
| ); | |
| } | |