mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-12-30 00:48:52 +00:00
* Fix(#5914) glossary & glossaryTerm displayName * Minor change to show glossary displayname in the tree
This commit is contained in:
parent
f23357ba68
commit
c5ebfdc7e1
@ -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 }) => <div>{children}</div>),
|
||||
Input: jest.fn().mockImplementation(({ children }) => <div>{children}</div>),
|
||||
Row: jest.fn().mockImplementation(({ children }) => <div>{children}</div>),
|
||||
Space: jest.fn().mockImplementation(({ children }) => <div>{children}</div>),
|
||||
Typography: {
|
||||
Title: jest
|
||||
.fn()
|
||||
.mockImplementation(({ children }) => <div>{children}</div>),
|
||||
},
|
||||
}));
|
||||
|
||||
const mockProps = {
|
||||
assetData: mockedAssetData,
|
||||
currentPage: 1,
|
||||
|
||||
@ -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<string>();
|
||||
/**
|
||||
* 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<string> = [];
|
||||
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 ? (
|
||||
<PageLayout classes="tw-h-full tw-px-6" leftPanel={fetchLeftPanel()}>
|
||||
<div
|
||||
className="tw-flex tw-justify-between tw-items-center"
|
||||
data-testid="header">
|
||||
<div
|
||||
className="tw-heading tw-text-link tw-text-base"
|
||||
data-testid="category-name">
|
||||
<div className="tw-text-link tw-text-base" data-testid="category-name">
|
||||
<TitleBreadcrumb
|
||||
titleLinks={breadcrumb}
|
||||
widthDeductions={
|
||||
@ -329,26 +362,81 @@ const GlossaryV1 = ({
|
||||
{isChildLoading ? (
|
||||
<Loader />
|
||||
) : (
|
||||
!isEmpty(selectedData) &&
|
||||
(isGlossaryActive ? (
|
||||
<GlossaryDetails
|
||||
glossary={selectedData as Glossary}
|
||||
handleUserRedirection={handleUserRedirection}
|
||||
isHasAccess={isHasAccess}
|
||||
updateGlossary={updateGlossary}
|
||||
/>
|
||||
) : (
|
||||
<GlossaryTermsV1
|
||||
assetData={assetData}
|
||||
currentPage={currentPage}
|
||||
glossaryTerm={selectedData as GlossaryTerm}
|
||||
handleGlossaryTermUpdate={handleGlossaryTermUpdate}
|
||||
handleUserRedirection={handleUserRedirection}
|
||||
isHasAccess={isHasAccess}
|
||||
onAssetPaginate={onAssetPaginate}
|
||||
onRelatedTermClick={onRelatedTermClick}
|
||||
/>
|
||||
))
|
||||
<>
|
||||
<div className="edit-input">
|
||||
{isNameEditing ? (
|
||||
<Row align="middle" gutter={8}>
|
||||
<Col>
|
||||
<Input
|
||||
className="input-width"
|
||||
data-testid="displayName"
|
||||
name="displayName"
|
||||
value={displayName}
|
||||
onChange={(e) => onDisplayNameChange(e.target.value)}
|
||||
/>
|
||||
</Col>
|
||||
<Col>
|
||||
<Button
|
||||
className="icon-buttons"
|
||||
data-testid="cancelAssociatedTag"
|
||||
size="custom"
|
||||
theme="primary"
|
||||
variant="contained"
|
||||
onMouseDown={() => setIsNameEditing(false)}>
|
||||
<FontAwesomeIcon
|
||||
className="tw-w-3.5 tw-h-3.5"
|
||||
icon="times"
|
||||
/>
|
||||
</Button>
|
||||
<Button
|
||||
className="icon-buttons"
|
||||
data-testid="saveAssociatedTag"
|
||||
size="custom"
|
||||
theme="primary"
|
||||
variant="contained"
|
||||
onMouseDown={onDisplayNameSave}>
|
||||
<FontAwesomeIcon
|
||||
className="tw-w-3.5 tw-h-3.5"
|
||||
icon="check"
|
||||
/>
|
||||
</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
) : (
|
||||
<Space className="display-name">
|
||||
<Title level={4}>{getEntityName(selectedData)}</Title>
|
||||
<button onClick={() => setIsNameEditing(true)}>
|
||||
<SVGIcons
|
||||
alt="icon-tag"
|
||||
className="tw-mx-1"
|
||||
icon={Icons.EDIT}
|
||||
width="16"
|
||||
/>
|
||||
</button>
|
||||
</Space>
|
||||
)}
|
||||
</div>
|
||||
{!isEmpty(selectedData) &&
|
||||
(isGlossaryActive ? (
|
||||
<GlossaryDetails
|
||||
glossary={selectedData as Glossary}
|
||||
handleUserRedirection={handleUserRedirection}
|
||||
isHasAccess={isHasAccess}
|
||||
updateGlossary={updateGlossary}
|
||||
/>
|
||||
) : (
|
||||
<GlossaryTermsV1
|
||||
assetData={assetData}
|
||||
currentPage={currentPage}
|
||||
glossaryTerm={selectedData as GlossaryTerm}
|
||||
handleGlossaryTermUpdate={handleGlossaryTermUpdate}
|
||||
handleUserRedirection={handleUserRedirection}
|
||||
isHasAccess={isHasAccess}
|
||||
onAssetPaginate={onAssetPaginate}
|
||||
onRelatedTermClick={onRelatedTermClick}
|
||||
/>
|
||||
))}
|
||||
</>
|
||||
)}
|
||||
{selectedData && isDelete && (
|
||||
<EntityDeleteModal
|
||||
|
||||
@ -0,0 +1,19 @@
|
||||
.display-name {
|
||||
.ant-typography {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.input-width {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.edit-input {
|
||||
padding: 1rem 0;
|
||||
}
|
||||
|
||||
.icon-buttons {
|
||||
padding: 0.2rem 0.2rem;
|
||||
border-radius: 0.2rem;
|
||||
margin-right: 0.3rem;
|
||||
}
|
||||
@ -30,7 +30,6 @@ import {
|
||||
GlossaryTerm,
|
||||
TermReference,
|
||||
} from '../../generated/entity/data/glossaryTerm';
|
||||
import { EntityReference } from '../../generated/entity/type';
|
||||
import { LabelType, State, TagSource } from '../../generated/type/tagLabel';
|
||||
import jsonData from '../../jsons/en';
|
||||
import { getEntityName } from '../../utils/CommonUtils';
|
||||
@ -623,16 +622,13 @@ const GlossaryTermsV1 = ({
|
||||
<div
|
||||
className="tw-w-full tw-h-full tw-flex tw-flex-col"
|
||||
data-testid="glossary-term">
|
||||
<p className="tw-text-lg tw-font-medium tw--mt-3">
|
||||
{getEntityName(glossaryTerm as unknown as EntityReference)}
|
||||
</p>
|
||||
{/* TODO: Add this stat when supporting status updation */}
|
||||
{/* <div className="tw-flex tw-gap-11 tw-mb-2">
|
||||
<div className="tw-font-medium">Status</div>
|
||||
<div>{glossaryTerm.status}</div>
|
||||
</div> */}
|
||||
|
||||
<div className="tw-flex tw-flex-wrap tw-group tw-mt-3" data-testid="tags">
|
||||
<div className="tw-flex tw-flex-wrap tw-group" data-testid="tags">
|
||||
{!isTagEditable && (
|
||||
<>
|
||||
{glossaryTerm?.tags && glossaryTerm.tags.length > 0 && (
|
||||
|
||||
@ -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 || '';
|
||||
};
|
||||
|
||||
@ -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),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user