feat(ui): include parent term groups, domains in glossary, domain dropdown (#9715)

This commit is contained in:
gaurav2733 2024-01-29 15:26:14 +05:30 committed by GitHub
parent 2bb4b73f98
commit dc16c73937
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 138 additions and 43 deletions

View File

@ -10,11 +10,19 @@ import { BrowserWrapper } from '../../../shared/tags/AddTagsTermsModal';
import TermLabel from '../../../shared/TermLabel';
import { useEntityRegistry } from '../../../useEntityRegistry';
import { useEntityData, useRefetch } from '../../shared/EntityContext';
import ParentEntities from '../../../search/filters/ParentEntities';
import { getParentEntities } from '../../../search/filters/utils';
const StyledSelect = styled(Select)`
width: 480px;
`;
const SearchResultContainer = styled.div`
display: flex;
flex-direction: column;
justify-content: center;
`;
interface Props {
onClose: () => void;
relationshipType: TermRelationshipType;
@ -68,7 +76,10 @@ function AddRelatedTermsModal(props: Props) {
return (
<Select.Option value={result.entity.urn} key={result.entity.urn} name={displayName}>
<TermLabel name={displayName} />
<SearchResultContainer>
<ParentEntities parentEntities={getParentEntities(result.entity) || []} />
<TermLabel name={displayName} />
</SearchResultContainer>
</Select.Option>
);
});

View File

@ -1,5 +1,6 @@
import React from 'react';
import { Select } from 'antd';
import styled from 'styled-components';
import { EntityType, GlossaryNode, SearchResult } from '../../../../types.generated';
import { useEntityRegistry } from '../../../useEntityRegistry';
import { useEntityData } from '../EntityContext';
@ -7,6 +8,14 @@ import ClickOutside from '../../../shared/ClickOutside';
import GlossaryBrowser from '../../../glossary/GlossaryBrowser/GlossaryBrowser';
import { BrowserWrapper } from '../../../shared/tags/AddTagsTermsModal';
import useParentSelector from './useParentSelector';
import ParentEntities from '../../../search/filters/ParentEntities';
import { getParentGlossary } from '../../../glossary/utils';
const SearchResultContainer = styled.div`
display: flex;
flex-direction: column;
justify-content: center;
`;
// filter out entity itself and its children
export function filterResultsForMove(entity: GlossaryNode, entityUrn: string) {
@ -46,10 +55,9 @@ function NodeParentSelect(props: Props) {
setSelectedParentUrn,
});
let nodeSearchResults: SearchResult[] = [];
if (isMoving) {
nodeSearchResults = searchResults.filter((r) => filterResultsForMove(r.entity as GlossaryNode, entityDataUrn));
}
const nodeSearchResults: SearchResult[] = searchResults.filter((r) =>
filterResultsForMove(r.entity as GlossaryNode, entityDataUrn),
);
const isShowingGlossaryBrowser = !searchQuery && isFocusedOnInput;
const shouldHideSelf = isMoving && entityType === EntityType.GlossaryNode;
@ -70,7 +78,10 @@ function NodeParentSelect(props: Props) {
>
{nodeSearchResults?.map((result) => (
<Select.Option key={result?.entity?.urn} value={result.entity.urn}>
{entityRegistry.getDisplayName(result.entity.type, result.entity)}
<SearchResultContainer>
<ParentEntities parentEntities={getParentGlossary(result.entity, entityRegistry)} />
{entityRegistry.getDisplayName(result.entity.type, result.entity)}
</SearchResultContainer>
</Select.Option>
))}
</Select>

View File

@ -16,6 +16,8 @@ import DomainNavigator from '../../../../../../domain/nestedDomains/domainNaviga
import ClickOutside from '../../../../../../shared/ClickOutside';
import { ANTD_GRAY } from '../../../../constants';
import { getModalDomContainer } from '../../../../../../../utils/focus';
import ParentEntities from '../../../../../../search/filters/ParentEntities';
import { getParentDomains } from '../../../../../../domain/utils';
type Props = {
urns: string[];
@ -44,6 +46,12 @@ const LoadingWrapper = styled.div`
}
`;
const SearchResultContainer = styled.div`
display: flex;
flex-direction: column;
justify-content: center;
`;
export const SetDomainModal = ({ urns, onCloseModal, refetch, defaultValue, onOkOverride, titleOverride }: Props) => {
const entityRegistry = useEntityRegistry();
const [isFocusedOnInput, setIsFocusedOnInput] = useState(false);
@ -88,7 +96,10 @@ export const SetDomainModal = ({ urns, onCloseModal, refetch, defaultValue, onOk
const displayName = entityRegistry.getDisplayName(entity.type, entity);
return (
<Select.Option value={entity.urn} key={entity.urn}>
<DomainLabel name={displayName} />
<SearchResultContainer>
<ParentEntities parentEntities={getParentDomains(entity, entityRegistry)} />
<DomainLabel name={displayName} />
</SearchResultContainer>
</Select.Option>
);
};

View File

@ -0,0 +1,56 @@
// Create a new component called SearchResultItem.js
import React from 'react';
import { Link } from 'react-router-dom';
import Highlight from 'react-highlighter';
import styled from 'styled-components/macro';
import { Entity } from '../../types.generated';
import { IconStyleType } from '../entity/Entity';
import { ANTD_GRAY } from '../entity/shared/constants';
import ParentEntities from '../search/filters/ParentEntities';
import { getParentGlossary } from './utils';
import EntityRegistry from '../entity/EntityRegistry';
type Props = {
entity: Entity;
entityRegistry: EntityRegistry;
query: string;
onResultClick: () => void;
};
const SearchResult = styled(Link)`
color: #262626;
display: flex;
align-items: center;
gap: 8px;
height: 100%;
padding: 6px 8px;
width: 100%;
&:hover {
background-color: ${ANTD_GRAY[3]};
color: #262626;
}
`;
const IconWrapper = styled.span``;
const highlightMatchStyle = {
fontWeight: 'bold',
background: 'none',
padding: 0,
};
function GlossarySearchResultItem({ entity, entityRegistry, query, onResultClick }: Props) {
return (
<SearchResult to={entityRegistry.getEntityUrl(entity.type, entity.urn)} onClick={onResultClick}>
<IconWrapper>{entityRegistry.getIcon(entity.type, 12, IconStyleType.TAB_VIEW)}</IconWrapper>
<div>
<ParentEntities parentEntities={getParentGlossary(entity, entityRegistry)} />
<Highlight matchStyle={highlightMatchStyle} search={query}>
{entityRegistry.getDisplayName(entity.type, entity)}
</Highlight>
</div>
</SearchResult>
);
}
export default GlossarySearchResultItem;

View File

@ -1,13 +1,12 @@
import React, { useState } from 'react';
import { Link } from 'react-router-dom';
import styled from 'styled-components/macro';
import { useGetSearchResultsForMultipleQuery } from '../../graphql/search.generated';
import { EntityType } from '../../types.generated';
import { IconStyleType } from '../entity/Entity';
import { ANTD_GRAY } from '../entity/shared/constants';
import { SearchBar } from '../search/SearchBar';
import ClickOutside from '../shared/ClickOutside';
import { useEntityRegistry } from '../useEntityRegistry';
import GloassarySearchResultItem from './GloassarySearchResultItem';
const GlossarySearchWrapper = styled.div`
position: relative;
@ -28,20 +27,10 @@ const ResultsWrapper = styled.div`
top: 45px;
`;
const SearchResult = styled(Link)`
color: #262626;
display: inline-block;
height: 100%;
padding: 6px 8px;
width: 100%;
&:hover {
background-color: ${ANTD_GRAY[3]};
color: #262626;
}
`;
const IconWrapper = styled.span`
margin-right: 8px;
const TermNodeName = styled.span`
margin-top: 12px;
color: ${ANTD_GRAY[8]};
font-weight: bold;
`;
function GlossarySearch() {
@ -63,6 +52,21 @@ function GlossarySearch() {
const searchResults = data?.searchAcrossEntities?.searchResults;
const renderSearchResults = () => (
<ResultsWrapper>
<TermNodeName>Glossary Terms</TermNodeName>
{searchResults?.map((result) => (
<GloassarySearchResultItem
key={result.entity.urn}
entity={result.entity}
entityRegistry={entityRegistry}
query={query}
onResultClick={() => setIsSearchBarFocused(false)}
/>
))}
</ResultsWrapper>
);
return (
<GlossarySearchWrapper>
<ClickOutside onClickOutside={() => setIsSearchBarFocused(false)}>
@ -84,23 +88,8 @@ function GlossarySearch() {
entityRegistry={entityRegistry}
onFocus={() => setIsSearchBarFocused(true)}
/>
{isSearchBarFocused && searchResults && !!searchResults.length && (
<ResultsWrapper>
{searchResults.map((result) => {
return (
<SearchResult
to={`${entityRegistry.getEntityUrl(result.entity.type, result.entity.urn)}`}
onClick={() => setIsSearchBarFocused(false)}
>
<IconWrapper>
{entityRegistry.getIcon(result.entity.type, 12, IconStyleType.ACCENT)}
</IconWrapper>
{entityRegistry.getDisplayName(result.entity.type, result.entity)}
</SearchResult>
);
})}
</ResultsWrapper>
)}
{isSearchBarFocused && searchResults && !!searchResults.length && renderSearchResults()}
</ClickOutside>
</GlossarySearchWrapper>
);

View File

@ -1,4 +1,5 @@
import { EntityType } from '../../types.generated';
import { Entity, EntityType } from '../../types.generated';
import EntityRegistry from '../entity/EntityRegistry';
import { GenericEntityProperties } from '../entity/shared/types';
export const ROOT_NODES = 'rootNodes';
@ -25,3 +26,8 @@ export function updateGlossarySidebar(
) {
setUrnsToUpdate([...urnsToUpdate, ...parentNodesToUpdate]);
}
export function getParentGlossary<T extends Entity>(node: T, entityRegistry: EntityRegistry) {
const props = entityRegistry.getGenericEntityProperties(EntityType.GlossaryNode, node);
return props?.parentNodes?.nodes ?? [];
}

View File

@ -5,7 +5,7 @@ const DomainContainerWrapper = styled.div`
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px;
padding: 2px;
`;
const DomainContentWrapper = styled.div`

View File

@ -20,6 +20,8 @@ import { FORBIDDEN_URN_CHARS_REGEX, handleBatchError } from '../../entity/shared
import { TagTermLabel } from './TagTermLabel';
import { ENTER_KEY_CODE } from '../constants';
import { getModalDomContainer } from '../../../utils/focus';
import ParentEntities from '../../search/filters/ParentEntities';
import { getParentEntities } from '../../search/filters/utils';
export enum OperationType {
ADD,
@ -69,6 +71,12 @@ export const BrowserWrapper = styled.div<{ isHidden: boolean; width?: string; ma
`}
`;
const SearchResultContainer = styled.div`
display: flex;
flex-direction: column;
justify-content: center;
`;
const CREATE_TAG_VALUE = '____reserved____.createTagValue';
const isValidTagName = (tagName: string) => {
@ -139,7 +147,10 @@ export default function EditTagTermsModal({
const tagOrTermComponent = <TagTermLabel entity={entity} />;
return (
<Select.Option data-testid="tag-term-option" value={entity.urn} key={entity.urn} name={displayName}>
{tagOrTermComponent}
<SearchResultContainer>
<ParentEntities parentEntities={getParentEntities(entity) || []} />
{tagOrTermComponent}
</SearchResultContainer>
</Select.Option>
);
};