diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Entity/EntityInfoDrawer/EdgeInfoDrawer.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Entity/EntityInfoDrawer/EdgeInfoDrawer.component.tsx index 97d63d956cb..ec56f9c4032 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Entity/EntityInfoDrawer/EdgeInfoDrawer.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Entity/EntityInfoDrawer/EdgeInfoDrawer.component.tsx @@ -21,8 +21,10 @@ import { Node } from 'reactflow'; import { ReactComponent as EditIcon } from '../../../assets/svg/edit-new.svg'; import DescriptionV1 from '../../../components/common/EntityDescription/DescriptionV1'; import { DE_ACTIVE_COLOR } from '../../../constants/constants'; +import { LINEAGE_SOURCE } from '../../../constants/Lineage.constants'; import { CSMode } from '../../../enums/codemirror.enum'; import { EntityType } from '../../../enums/entity.enum'; +import { Source } from '../../../generated/type/entityLineage'; import { getNameFromFQN } from '../../../utils/CommonUtils'; import { getLineageDetailsObject } from '../../../utils/EntityLineageUtils'; import entityUtilClassBase from '../../../utils/EntityUtilClassBase'; @@ -266,6 +268,15 @@ const EdgeInfoDrawer = ({ )} + + + + {`${t('label.lineage-source')}`} + + + {LINEAGE_SOURCE[edgeEntity.source as keyof typeof Source]} + + )} diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Entity/EntityInfoDrawer/EdgeInfoDrawer.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Entity/EntityInfoDrawer/EdgeInfoDrawer.test.tsx new file mode 100644 index 00000000000..7904fd2bbd9 --- /dev/null +++ b/openmetadata-ui/src/main/resources/ui/src/components/Entity/EntityInfoDrawer/EdgeInfoDrawer.test.tsx @@ -0,0 +1,163 @@ +/* + * Copyright 2024 Collate. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { act, fireEvent, render, screen } from '@testing-library/react'; +import React from 'react'; +import { Edge } from 'reactflow'; +import { MOCK_NODES_AND_EDGES } from '../../../mocks/Lineage.mock'; +import EdgeInfoDrawer from './EdgeInfoDrawer.component'; + +jest.mock('../../../components/common/EntityDescription/DescriptionV1', () => + jest.fn().mockImplementation(({ onDescriptionUpdate }) => ( +
+ DescriptionV1 + +
+ )) +); + +jest.mock('../../../utils/CommonUtils', () => ({ + getNameFromFQN: jest.fn().mockReturnValue('getNameFromFQN'), +})); + +jest.mock('../../../utils/EntityUtils', () => ({ + getEntityName: jest.fn().mockReturnValue('username'), +})); + +jest.mock('../../common/Loader/Loader', () => + jest.fn().mockImplementation(() =>
Loader
) +); + +jest.mock('../../Database/SchemaEditor/SchemaEditor', () => { + return jest.fn().mockImplementation(() =>
SchemaEditor.component
); +}); + +jest.mock('../../Modals/ModalWithQueryEditor/ModalWithQueryEditor', () => { + return jest.fn().mockImplementation(() =>
ModalWithQueryEditor
); +}); + +jest.mock('antd', () => ({ + ...jest.requireActual('antd'), + Drawer: jest.fn().mockImplementation(({ children, title }) => ( +
+ Drawer +
{title}
+
{children}
+
+ )), +})); + +const mockOnEdgeDetailsUpdate = jest.fn(); +const mockEdgeInfoDrawer = { + edge: { + id: 'edge-5c97531f-d164-4707-842e-af52e0c43e26-5d816d56-40a2-493f-ae9d-012f1cd337dd', + source: '5c97531f-d164-4707-842e-af52e0c43e26', + target: '5d816d56-40a2-493f-ae9d-012f1cd337dd', + type: 'buttonedge', + animated: false, + style: { + strokeWidth: '2px', + }, + markerEnd: { + type: 'arrowclosed', + }, + data: { + edge: { + toEntity: { + fqn: 'RedshiftProd.dev.demo_dbt_jaffle.customers', + id: '5d816d56-40a2-493f-ae9d-012f1cd337dd', + type: 'table', + }, + pipeline: null, + fromEntity: { + fqn: 'RedshiftProd.dev.demo_dbt_jaffle.stg_orders', + id: '5c97531f-d164-4707-842e-af52e0c43e26', + type: 'table', + }, + sqlQuery: null, + description: null, + source: 'DbtLineage', + doc_id: + '5c97531f-d164-4707-842e-af52e0c43e26-5d816d56-40a2-493f-ae9d-012f1cd337dd', + }, + isColumnLineage: false, + isPipelineRootNode: false, + }, + selected: true, + } as Edge, + nodes: MOCK_NODES_AND_EDGES.nodes, + visible: true, + hasEditAccess: true, + onEdgeDetailsUpdate: mockOnEdgeDetailsUpdate, + onClose: jest.fn(), +}; + +describe('EdgeInfoDrawer Component', () => { + it('should render the component', async () => { + render(); + + expect(await screen.findByTestId('title')).toHaveTextContent( + 'label.edge-information' + ); + + expect(await screen.findByTestId('description-v1')).toBeInTheDocument(); + expect( + await screen.findByText('label.sql-uppercase-query') + ).toBeInTheDocument(); + expect(await screen.findByTestId('edit-sql')).toBeInTheDocument(); + }); + + it('should render no query if no query is present', async () => { + render(); + + expect( + await screen.findByText('server.no-query-available') + ).toBeInTheDocument(); + }); + + it('should render source of lineage', async () => { + render(); + + expect(await screen.findByText('label.lineage-source')).toBeInTheDocument(); + expect(await screen.findByText('dbt Lineage')).toBeInTheDocument(); + }); + + it('should call onEdgeDetailsUpdate on update description', async () => { + render(); + const updateDescriptionButton = await screen.findByTestId( + 'update-description-button' + ); + await act(async () => { + fireEvent.click(updateDescriptionButton); + }); + + expect(mockOnEdgeDetailsUpdate).toHaveBeenCalledWith( + expect.objectContaining({ + edge: expect.objectContaining({ + lineageDetails: expect.objectContaining({ + description: 'updatedHTML', + }), + }), + }) + ); + }); + + it('should not render edit SQL button if has no edit access', () => { + render(); + + expect(screen.queryByTestId('edit-sql')).not.toBeInTheDocument(); + }); +}); diff --git a/openmetadata-ui/src/main/resources/ui/src/constants/Lineage.constants.ts b/openmetadata-ui/src/main/resources/ui/src/constants/Lineage.constants.ts index 5872d803d3b..5d42310c619 100644 --- a/openmetadata-ui/src/main/resources/ui/src/constants/Lineage.constants.ts +++ b/openmetadata-ui/src/main/resources/ui/src/constants/Lineage.constants.ts @@ -14,6 +14,7 @@ import { t } from 'i18next'; import { ElementLoadingState } from '../components/Entity/EntityLineage/EntityLineage.interface'; import { SearchIndex } from '../enums/search.enum'; +import { Source } from '../generated/type/entityLineage'; export const FOREIGN_OBJECT_SIZE = 40; export const ZOOM_VALUE = 0.75; @@ -73,3 +74,13 @@ export const LINEAGE_DEFAULT_QUICK_FILTERS = [ 'owner.displayName.keyword', 'tags.tagFQN', ]; + +export const LINEAGE_SOURCE: { [key in Source]: string } = { + [Source.DashboardLineage]: 'Dashboard Lineage', + [Source.DbtLineage]: 'dbt Lineage', + [Source.Manual]: 'Manual', + [Source.PipelineLineage]: 'Pipeline Lineage', + [Source.QueryLineage]: 'Query Lineage', + [Source.SparkLineage]: 'Spark Lineage', + [Source.ViewLineage]: 'View Lineage', +}; diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/de-de.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/de-de.json index b4a805bd6c9..3487c87ce90 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/de-de.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/de-de.json @@ -616,6 +616,7 @@ "lineage-ingestion": "Abstammungsinjektion", "lineage-lowercase": "Abstammung", "lineage-node-lowercase": "Abstammungsknoten", + "lineage-source": "Source of Lineage", "list": "Liste", "list-entity": "{{entity}}-Liste", "live": "Live", diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/en-us.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/en-us.json index 20bc9e655ae..12aedd13e0c 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/en-us.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/en-us.json @@ -616,6 +616,7 @@ "lineage-ingestion": "Lineage Ingestion", "lineage-lowercase": "lineage", "lineage-node-lowercase": "lineage node", + "lineage-source": "Source of Lineage", "list": "List", "list-entity": "List {{entity}}", "live": "Live", diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/es-es.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/es-es.json index 6d347ae084c..234c7ed69e0 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/es-es.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/es-es.json @@ -613,9 +613,10 @@ "lineage": "Linaje", "lineage-config": "Configuración del linaje", "lineage-data-lowercase": "lineage data", - "lineage-ingestion": "Ingesta de linaje", - "lineage-lowercase": "linaje", - "lineage-node-lowercase": "nodo de linaje", + "lineage-ingestion": "Ingesta de lineaje", + "lineage-lowercase": "lineaje", + "lineage-node-lowercase": "lineage node", + "lineage-source": "Source of Lineage", "list": "Lista", "list-entity": "Lista de {{entity}}", "live": "Vivo", diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/fr-fr.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/fr-fr.json index 0e3519fdefe..5f6e4b05c41 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/fr-fr.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/fr-fr.json @@ -616,6 +616,7 @@ "lineage-ingestion": "Ingestion de la Traçabilité", "lineage-lowercase": "traçabilité", "lineage-node-lowercase": "Nœud de Traçabilité", + "lineage-source": "Source of Lineage", "list": "Liste", "list-entity": "Liste de {{entity}}", "live": "En Direct", diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/he-he.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/he-he.json index fabd1e11d9a..e0bca98c5ff 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/he-he.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/he-he.json @@ -616,6 +616,7 @@ "lineage-ingestion": "כניסת שורשים", "lineage-lowercase": "שורשים", "lineage-node-lowercase": "צומת שורש", + "lineage-source": "Source of Lineage", "list": "רשימה", "list-entity": "רשימת {{entity}}", "live": "שידור חי", diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/ja-jp.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/ja-jp.json index 12acc956ea5..1f187b25a92 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/ja-jp.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/ja-jp.json @@ -616,6 +616,7 @@ "lineage-ingestion": "リネージのインジェスチョン", "lineage-lowercase": "リネージ", "lineage-node-lowercase": "lineage node", + "lineage-source": "Source of Lineage", "list": "リスト", "list-entity": "{{entity}}のリスト", "live": "Live", diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/nl-nl.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/nl-nl.json index e09b93fd682..5b1e53899a5 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/nl-nl.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/nl-nl.json @@ -616,6 +616,7 @@ "lineage-ingestion": "Herkomstingestie", "lineage-lowercase": "herkomst", "lineage-node-lowercase": "herkomstknooppunt", + "lineage-source": "Source of Lineage", "list": "Lijst", "list-entity": "Lijst {{entity}}", "live": "Live", diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/pt-br.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/pt-br.json index 28a95c64dd5..da1c11557f9 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/pt-br.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/pt-br.json @@ -616,6 +616,7 @@ "lineage-ingestion": "Ingestão de Linhagem", "lineage-lowercase": "linhagem", "lineage-node-lowercase": "nó de linhagem", + "lineage-source": "Source of Lineage", "list": "Lista", "list-entity": "Listar {{entity}}", "live": "Ao Vivo", diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/ru-ru.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/ru-ru.json index 26dc5ff7fdb..439fbe58f3e 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/ru-ru.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/ru-ru.json @@ -616,6 +616,7 @@ "lineage-ingestion": "Получение проихождения", "lineage-lowercase": "происходение", "lineage-node-lowercase": "узел происхождения", + "lineage-source": "Source of Lineage", "list": "Список", "list-entity": "Список {{entity}}", "live": "Процесс", diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/zh-cn.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/zh-cn.json index 9e1a4634191..f4d3278a4d7 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/zh-cn.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/zh-cn.json @@ -616,6 +616,7 @@ "lineage-ingestion": "血缘关系提取", "lineage-lowercase": "血缘", "lineage-node-lowercase": "血缘关系节点", + "lineage-source": "Source of Lineage", "list": "列表", "list-entity": "列出{{entity}}", "live": "实时",