import React, { FormEvent, useCallback, useEffect, useState } from 'react'; import { ClickOutsideWrapper } from '@grafana/ui'; import { RolePickerMenu } from './RolePickerMenu'; import { RolePickerInput } from './RolePickerInput'; import { Role, OrgRole } from 'app/types'; export interface Props { builtInRole: OrgRole; getRoles: () => Promise; getRoleOptions: () => Promise; getBuiltinRoles: () => Promise>; onRolesChange: (newRoles: string[]) => void; onBuiltinRoleChange: (newRole: OrgRole) => void; disabled?: boolean; builtinRolesDisabled?: boolean; } export const RolePicker = ({ builtInRole, getRoles, getRoleOptions, getBuiltinRoles, onRolesChange, onBuiltinRoleChange, disabled, builtinRolesDisabled, }: Props): JSX.Element | null => { const [isOpen, setOpen] = useState(false); const [roleOptions, setRoleOptions] = useState([]); const [appliedRoles, setAppliedRoles] = useState([]); const [selectedRoles, setSelectedRoles] = useState([]); const [selectedBuiltInRole, setSelectedBuiltInRole] = useState(builtInRole); const [builtInRoles, setBuiltinRoles] = useState>({}); const [query, setQuery] = useState(''); const [isLoading, setIsLoading] = useState(true); useEffect(() => { async function fetchOptions() { try { let options = await getRoleOptions(); setRoleOptions(options.filter((option) => !option.name?.startsWith('managed:'))); const builtInRoles = await getBuiltinRoles(); setBuiltinRoles(builtInRoles); const userRoles = await getRoles(); setAppliedRoles(userRoles); setSelectedRoles(userRoles); } catch (e) { // TODO handle error console.error('Error loading options'); } finally { setIsLoading(false); } } fetchOptions(); }, [getRoles, getRoleOptions, getBuiltinRoles, builtInRole]); const onOpen = useCallback( (event: FormEvent) => { if (!disabled) { event.preventDefault(); event.stopPropagation(); setOpen(true); } }, [setOpen, disabled] ); const onClose = useCallback(() => { setOpen(false); setQuery(''); setSelectedRoles(appliedRoles); setSelectedBuiltInRole(builtInRole); }, [appliedRoles, builtInRole]); // Only call onClose if menu is open. Prevent unnecessary calls for multiple pickers on the page. const onClickOutside = () => isOpen && onClose(); const onInputChange = (query?: string) => { if (query) { setQuery(query); } else { setQuery(''); } }; const onSelect = (roles: Role[]) => { setSelectedRoles(roles); }; const onBuiltInRoleSelect = (role: OrgRole) => { setSelectedBuiltInRole(role); }; const onUpdate = (newBuiltInRole: OrgRole, newRoles: string[]) => { onBuiltinRoleChange(newBuiltInRole); onRolesChange(newRoles); setOpen(false); setQuery(''); }; const getOptions = () => { if (query && query.trim() !== '') { return roleOptions.filter((option) => option.name?.toLowerCase().includes(query.toLowerCase())); } return roleOptions; }; if (isLoading) { return null; } return (
{isOpen && ( )}
); };