import React from 'react'; import { Form, Select, Switch, Tag, Typography } from 'antd'; import styled from 'styled-components'; import { Maybe } from 'graphql/jsutils/Maybe'; import { useEntityRegistry } from '../../useEntityRegistry'; import { ActorFilter, CorpUser, EntityType, PolicyType, SearchResult } from '../../../types.generated'; import { useGetSearchResultsLazyQuery } from '../../../graphql/search.generated'; import { useListOwnershipTypesQuery } from '../../../graphql/ownership.generated'; import { CustomAvatar } from '../../shared/avatar'; type Props = { policyType: PolicyType; actors: ActorFilter; setActors: (actors: ActorFilter) => void; }; const SearchResultContainer = styled.div` display: flex; justify-content: space-between; align-items: center; padding: 2px; `; const ActorForm = styled(Form)` margin: 12px; margin-top: 36px; margin-bottom: 40px; `; const ActorFormHeader = styled.div` margin-bottom: 28px; `; const SearchResultContent = styled.div` display: flex; justify-content: center; align-items: center; `; const OwnershipWrapper = styled.div` margin-top: 12px; `; /** * Component used to construct the "actors" portion of a DataHub * access Policy by populating an ActorFilter object. */ export default function PolicyActorForm({ policyType, actors, setActors }: Props) { const entityRegistry = useEntityRegistry(); // Search for actors while building policy. const [userSearch, { data: userSearchData }] = useGetSearchResultsLazyQuery(); const [groupSearch, { data: groupSearchData }] = useGetSearchResultsLazyQuery(); const { data: ownershipData } = useListOwnershipTypesQuery({ variables: { input: {}, }, }); const ownershipTypes = ownershipData?.listOwnershipTypes?.ownershipTypes.filter((type) => type.urn !== 'urn:li:ownershipType:none') || []; const ownershipTypesMap = Object.fromEntries(ownershipTypes.map((type) => [type.urn, type.info?.name])); // Toggle the "Owners" switch const onToggleAppliesToOwners = (value: boolean) => { setActors({ ...actors, resourceOwners: value, resourceOwnersTypes: value ? actors.resourceOwnersTypes : null, }); }; const onSelectOwnershipTypeActor = (newType: string) => { const newResourceOwnersTypes: Maybe = [...(actors.resourceOwnersTypes || []), newType]; setActors({ ...actors, resourceOwnersTypes: newResourceOwnersTypes, }); }; const onDeselectOwnershipTypeActor = (type: string) => { const newResourceOwnersTypes: Maybe = actors.resourceOwnersTypes?.filter((u: string) => u !== type); setActors({ ...actors, resourceOwnersTypes: newResourceOwnersTypes?.length ? newResourceOwnersTypes : null, }); }; // When a user search result is selected, add the urn to the ActorFilter const onSelectUserActor = (newUser: string) => { if (newUser === 'All') { setActors({ ...actors, allUsers: true, }); } else { const newUserActors = [...(actors.users || []), newUser]; setActors({ ...actors, users: newUserActors, }); } }; // When a user search result is deselected, remove the urn from the ActorFilter const onDeselectUserActor = (user: string) => { if (user === 'All') { setActors({ ...actors, allUsers: false, }); } else { const newUserActors = actors.users?.filter((u) => u !== user); setActors({ ...actors, users: newUserActors, }); } }; // When a group search result is selected, add the urn to the ActorFilter const onSelectGroupActor = (newGroup: string) => { if (newGroup === 'All') { setActors({ ...actors, allGroups: true, }); } else { const newGroupActors = [...(actors.groups || []), newGroup]; setActors({ ...actors, groups: newGroupActors, }); } }; // When a group search result is deselected, remove the urn from the ActorFilter const onDeselectGroupActor = (group: string) => { if (group === 'All') { setActors({ ...actors, allGroups: false, }); } else { const newGroupActors = actors.groups?.filter((g) => g !== group); setActors({ ...actors, groups: newGroupActors, }); } }; // Invokes the search API as the user types const handleSearch = (type: EntityType, text: string, searchQuery: any) => { searchQuery({ variables: { input: { type, query: text, start: 0, count: 10, }, }, }); }; // Invokes the user search API as the user types const handleUserSearch = (text: string) => { return handleSearch(EntityType.CorpUser, text, userSearch); }; // Invokes the group search API as the user types const handleGroupSearch = (text: string) => { return handleSearch(EntityType.CorpGroup, text, groupSearch); }; // Renders a search result in the select dropdown. const renderSearchResult = (result: SearchResult) => { const avatarUrl = result.entity.type === EntityType.CorpUser ? (result.entity as CorpUser).editableProperties?.pictureLink || undefined : undefined; const displayName = entityRegistry.getDisplayName(result.entity.type, result.entity); return (
{displayName}
); }; // Whether to show "owners" switch. const showAppliesToOwners = policyType === PolicyType.Metadata; // User and group dropdown search results! const userSearchResults = userSearchData?.search?.searchResults; const groupSearchResults = groupSearchData?.search?.searchResults; // Select dropdown values. const usersSelectValue = actors.allUsers ? ['All'] : actors.users || []; const groupsSelectValue = actors.allGroups ? ['All'] : actors.groups || []; const ownershipTypesSelectValue = actors.resourceOwnersTypes || []; const tagRender = (props) => { // eslint-disable-next-line react/prop-types const { label, closable, onClose, value } = props; const onPreventMouseDown = (event) => { event.preventDefault(); event.stopPropagation(); }; return ( {label} ); }; return ( Applies to Select the users & groups that this policy should apply to. {showAppliesToOwners && ( Owners} labelAlign="right"> Whether this policy should be apply to owners of the Metadata asset. If true, those who are marked as owners of a Metadata Asset, either directly or indirectly via a Group, will have the selected privileges. {actors.resourceOwners && ( List of types of ownership which will be used to match owners. If empty, the policies will applied to any type of ownership. )} )} Users}> Search for specific users that this policy should apply to, or select `All Users` to apply it to all users. Groups}> Search for specific groups that this policy should apply to, or select `All Groups` to apply it to all groups. ); }