diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/Glossary.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/Glossary.test.tsx index 311d3f65e15..bfc151db0aa 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/Glossary.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/Glossary.test.tsx @@ -49,6 +49,18 @@ jest.mock('../../components/GlossaryTerms/GlossaryTermsV1.component', () => { return jest.fn().mockReturnValue(<>Glossary-Term component); }); +jest.mock('antd', () => ({ + Col: jest.fn().mockImplementation(({ children }) =>
{children}
), + Input: jest.fn().mockImplementation(({ children }) =>
{children}
), + Row: jest.fn().mockImplementation(({ children }) =>
{children}
), + Space: jest.fn().mockImplementation(({ children }) =>
{children}
), + Typography: { + Title: jest + .fn() + .mockImplementation(({ children }) =>
{children}
), + }, +})); + const mockProps = { assetData: mockedAssetData, currentPage: 1, diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryV1.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryV1.component.tsx index b470d576308..6da0cb5b2be 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryV1.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryV1.component.tsx @@ -12,8 +12,9 @@ */ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { Col, Input, Row, Space, Typography } from 'antd'; import classNames from 'classnames'; -import { isEmpty } from 'lodash'; +import { cloneDeep, isEmpty } from 'lodash'; import { GlossaryTermAssets, LoadingState } from 'Models'; import RcTree from 'rc-tree'; import { DataNode, EventDataNode } from 'rc-tree/lib/interface'; @@ -27,7 +28,7 @@ import { GlossaryTerm } from '../../generated/entity/data/glossaryTerm'; import { useAuth } from '../../hooks/authHooks'; import { useAfterMount } from '../../hooks/useAfterMount'; import { ModifiedGlossaryData } from '../../pages/GlossaryPage/GlossaryPageV1.component'; -import { getEntityDeleteMessage } from '../../utils/CommonUtils'; +import { getEntityDeleteMessage, getEntityName } from '../../utils/CommonUtils'; import { generateTreeData } from '../../utils/GlossaryUtils'; import { getGlossaryPath } from '../../utils/RouterUtils'; import SVGIcons, { Icons } from '../../utils/SvgUtils'; @@ -43,6 +44,8 @@ import GlossaryDetails from '../GlossaryDetails/GlossaryDetails.component'; import GlossaryTermsV1 from '../GlossaryTerms/GlossaryTermsV1.component'; import Loader from '../Loader/Loader'; import EntityDeleteModal from '../Modals/EntityDeleteModal/EntityDeleteModal'; +import './GlossaryV1.style.less'; +const { Title } = Typography; type Props = { assetData: GlossaryTermAssets; @@ -120,12 +123,13 @@ const GlossaryV1 = ({ const [leftPanelWidth, setLeftPanelWidth] = useState( document.getElementById('glossary-left-panel')?.offsetWidth || 0 ); - + const [isNameEditing, setIsNameEditing] = useState(false); + const [displayName, setDisplayName] = useState(); /** * To create breadcrumb from the fqn * @param fqn fqn of glossary or glossary term */ - const handleBreadcrum = (fqn: string) => { + const handleBreadcrumb = (fqn: string) => { const arr = fqn.split(FQN_SEPARATOR_CHAR); const dataFQN: Array = []; const newData = arr.map((d, i) => { @@ -159,9 +163,36 @@ const GlossaryV1 = ({ if (selectedKey !== key) { handleChildLoading(true); handleSelectedData(key); + setIsNameEditing(false); } }; + const onDisplayNameChange = (value: string) => { + if (selectedData.displayName !== value) { + setDisplayName(value); + } + }; + + const onDisplayNameSave = () => { + let updatedDetails = cloneDeep(selectedData); + + updatedDetails = { + ...selectedData, + displayName: displayName, + }; + + if ( + (updatedDetails as GlossaryTerm)?.glossary || + (updatedDetails as GlossaryTerm)?.parent + ) { + handleGlossaryTermUpdate(updatedDetails as GlossaryTerm); + } else { + updateGlossary(updatedDetails as Glossary); + } + + setIsNameEditing(false); + }; + useEffect(() => { if (glossaryList.length) { const generatedData = generateTreeData(glossaryList); @@ -170,7 +201,7 @@ const GlossaryV1 = ({ }, [glossaryList]); useEffect(() => { - handleBreadcrum(selectedKey); + handleBreadcrumb(selectedKey); }, [selectedKey]); useAfterMount(() => { @@ -270,14 +301,16 @@ const GlossaryV1 = ({ ); }; + useEffect(() => { + setDisplayName(selectedData?.displayName); + }, [selectedData]); + return glossaryList.length ? (
-
+
) : ( - !isEmpty(selectedData) && - (isGlossaryActive ? ( - - ) : ( - - )) + <> +
+ {isNameEditing ? ( + + + onDisplayNameChange(e.target.value)} + /> + + + + + + + ) : ( + + {getEntityName(selectedData)} + + + )} +
+ {!isEmpty(selectedData) && + (isGlossaryActive ? ( + + ) : ( + + ))} + )} {selectedData && isDelete && ( -

- {getEntityName(glossaryTerm as unknown as EntityReference)} -

{/* TODO: Add this stat when supporting status updation */} {/*
Status
{glossaryTerm.status}
*/} -
+
{!isTagEditable && ( <> {glossaryTerm?.tags && glossaryTerm.tags.length > 0 && ( diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/CommonUtils.tsx b/openmetadata-ui/src/main/resources/ui/src/utils/CommonUtils.tsx index 4d88e280c38..b3900ae343e 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/CommonUtils.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/utils/CommonUtils.tsx @@ -42,6 +42,7 @@ import { EntityType, FqnPart, TabSpecificField } from '../enums/entity.enum'; import { Ownership } from '../enums/mydata.enum'; import { Dashboard } from '../generated/entity/data/dashboard'; import { Database } from '../generated/entity/data/database'; +import { GlossaryTerm } from '../generated/entity/data/glossaryTerm'; import { Pipeline } from '../generated/entity/data/pipeline'; import { Table } from '../generated/entity/data/table'; import { Topic } from '../generated/entity/data/topic'; @@ -628,6 +629,7 @@ export const getEntityName = ( | Team | Policy | Role + | GlossaryTerm ) => { return entity?.displayName || entity?.name || ''; }; diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/GlossaryUtils.ts b/openmetadata-ui/src/main/resources/ui/src/utils/GlossaryUtils.ts index b17a232686b..2b71dc4376f 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/GlossaryUtils.ts +++ b/openmetadata-ui/src/main/resources/ui/src/utils/GlossaryUtils.ts @@ -35,7 +35,7 @@ import { GlossaryTerm } from '../generated/entity/data/glossaryTerm'; import { ModifiedGlossaryData } from '../pages/GlossaryPage/GlossaryPageV1.component'; import { FileIcon, FolderIcon } from '../utils/svgconstant'; import { formatSearchGlossaryTermResponse } from './APIUtils'; -import { getNameFromFQN } from './CommonUtils'; +import { getEntityName } from './CommonUtils'; export interface GlossaryTermTreeNode { children?: GlossaryTermTreeNode[]; @@ -104,7 +104,7 @@ export const generateTreeData = (data: ModifiedGlossaryData[]): DataNode[] => { return d.children?.length ? { key: (d as GlossaryTerm)?.fullyQualifiedName || d.name, - title: getNameFromFQN(d.name), + title: getEntityName(d), children: generateTreeData(d.children as ModifiedGlossaryData[]), data: d, icon: ({ selected }) => @@ -112,7 +112,7 @@ export const generateTreeData = (data: ModifiedGlossaryData[]): DataNode[] => { } : { key: (d as GlossaryTerm)?.fullyQualifiedName || d.name, - title: getNameFromFQN(d.name), + title: getEntityName(d), data: d, icon: ({ selected }) => FileIcon(selected ? PRIMERY_COLOR : TEXT_BODY_COLOR),