From f16e5f2bf28681a4fc997b0012b2f9acf7b09db7 Mon Sep 17 00:00:00 2001 From: Chirag Madlani <12962843+chirag-madlani@users.noreply.github.com> Date: Tue, 30 Sep 2025 15:14:32 +0530 Subject: [PATCH] minor fix --- .../CustomControls.component.tsx | 8 +- .../EntityLineage/CustomControls.test.tsx | 332 ++++++++++++++++-- .../LineageTable/LineageTable.test.tsx | 119 +------ .../components/LineageTable/LineageTable.tsx | 26 +- .../ui/src/locale/languages/de-de.json | 1 + .../ui/src/locale/languages/en-us.json | 1 + .../ui/src/locale/languages/es-es.json | 1 + .../ui/src/locale/languages/fr-fr.json | 1 + .../ui/src/locale/languages/gl-es.json | 1 + .../ui/src/locale/languages/he-he.json | 1 + .../ui/src/locale/languages/ja-jp.json | 1 + .../ui/src/locale/languages/ko-kr.json | 1 + .../ui/src/locale/languages/mr-in.json | 1 + .../ui/src/locale/languages/nl-nl.json | 1 + .../ui/src/locale/languages/pr-pr.json | 1 + .../ui/src/locale/languages/pt-br.json | 1 + .../ui/src/locale/languages/pt-pt.json | 1 + .../ui/src/locale/languages/ru-ru.json | 1 + .../ui/src/locale/languages/th-th.json | 1 + .../ui/src/locale/languages/tr-tr.json | 1 + .../ui/src/locale/languages/zh-cn.json | 1 + .../ui/src/locale/languages/zh-tw.json | 1 + 22 files changed, 336 insertions(+), 167 deletions(-) diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Entity/EntityLineage/CustomControls.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Entity/EntityLineage/CustomControls.component.tsx index 79109514da3..771022fe350 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Entity/EntityLineage/CustomControls.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Entity/EntityLineage/CustomControls.component.tsx @@ -262,10 +262,10 @@ const CustomControls: FC<{ ); const handleExportClick = useCallback(() => { - if (activeTab === 'lineage') { - onExportClick([ExportTypes.CSV, ExportTypes.PNG]); - } else { + if (activeTab === 'impact_analysis') { onExportClick([ExportTypes.CSV], handleImpactAnalysisExport); + } else { + onExportClick([ExportTypes.CSV, ExportTypes.PNG]); } }, [activeTab, onExportClick]); @@ -354,7 +354,7 @@ const CustomControls: FC<{ arrow placement="top" title={t('label.export-as-type', { type: t('label.csv') })}> - handleExportClick}> + diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Entity/EntityLineage/CustomControls.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Entity/EntityLineage/CustomControls.test.tsx index c8fd32eb573..f4bc0fde387 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Entity/EntityLineage/CustomControls.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Entity/EntityLineage/CustomControls.test.tsx @@ -10,66 +10,328 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { render } from '@testing-library/react'; +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; import { MemoryRouter } from 'react-router-dom'; -import { LINEAGE_TAB_VIEW } from '../../../constants/Lineage.constants'; -import { LineageLayer } from '../../../generated/settings/settings'; +import { EntityType } from '../../../enums/entity.enum'; import CustomControlsComponent from './CustomControls.component'; -const mockOnEditLineageClick = jest.fn(); const mockOnExportClick = jest.fn(); -const mockHandleActiveViewTabChange = jest.fn(); +const mockOnLineageConfigUpdate = jest.fn(); +const mockSetSelectedQuickFilters = jest.fn(); +const mockOnSearchValueChange = jest.fn(); + +const mockLineageConfig = { + upstreamDepth: 3, + downstreamDepth: 3, + nodesPerLayer: 50, +}; + +const mockNavigate = jest.fn(); +const mockLocation = { + search: '?mode=lineage&depth=3&dir=downstream', +}; + +const defaultProps = { + nodeDepthOptions: [1, 2, 3, 4, 5], + onSearchValueChange: mockOnSearchValueChange, + searchValue: '', +}; + +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useNavigate: () => mockNavigate, + useLocation: () => mockLocation, +})); jest.mock('./LineageSearchSelect/LineageSearchSelect', () => - jest.fn().mockReturnValue(

LineageSearchSelect

) + jest + .fn() + .mockReturnValue( +
LineageSearchSelect
+ ) ); jest.mock('../../Explore/ExploreQuickFilters', () => - jest.fn().mockReturnValue(

ExploreQuickFilters

) + jest + .fn() + .mockReturnValue( +
ExploreQuickFilters
+ ) ); -jest.mock('reactflow', () => ({ - Position: () => ({ - Left: 'left', - Top: 'top', - Right: 'right', - Bottom: 'bottom', - }), - MarkerType: () => ({ - Arrow: 'arrow', - ArrowClosed: 'arrowclosed', - }), -})); +jest.mock('./LineageConfigModal', () => + jest.fn(({ visible, onCancel, onSave }) => + visible ? ( +
+ + +
+ ) : null + ) +); + +jest.mock('../../common/SearchBarComponent/SearchBar.component', () => + jest.fn(({ onSearch, searchValue, placeholder }) => ( + onSearch(e.target.value)} + /> + )) +); jest.mock('../../../context/LineageProvider/LineageProvider', () => ({ useLineageProvider: jest.fn().mockImplementation(() => ({ - onLineageEditClick: mockOnEditLineageClick, onExportClick: mockOnExportClick, - activeLayer: [LineageLayer.ColumnLevelLineage], + onLineageConfigUpdate: mockOnLineageConfigUpdate, selectedQuickFilters: [], - setSelectedQuickFilters: jest.fn(), + setSelectedQuickFilters: mockSetSelectedQuickFilters, + lineageConfig: mockLineageConfig, + nodes: [], })), })); +jest.mock('../../../hooks/useFqn', () => ({ + useFqn: jest.fn().mockReturnValue({ fqn: 'test.table' }), +})); + +jest.mock('../../../utils/useRequiredParams', () => ({ + useRequiredParams: jest + .fn() + .mockReturnValue({ entityType: EntityType.TABLE }), +})); + +jest.mock('../../../rest/lineageAPI', () => ({ + exportLineageByEntityCountAsync: jest.fn(), +})); + +// Mock window.location +Object.defineProperty(window, 'location', { + value: { + search: '?mode=lineage&depth=3&dir=downstream', + }, + writable: true, +}); + describe('CustomControls', () => { - afterEach(() => { + beforeEach(() => { jest.clearAllMocks(); }); - it('calls onEditLinageClick on Edit Lineage button click', () => { - const { getByText } = render( - , - { wrapper: MemoryRouter } + it('renders all main control buttons', () => { + render(, { + wrapper: MemoryRouter, + }); + + expect(screen.getByLabelText('label.filter-plural')).toBeInTheDocument(); + expect(screen.getByText('label.lineage')).toBeInTheDocument(); + expect(screen.getByText('label.impact-analysis')).toBeInTheDocument(); + expect(screen.getByLabelText('label.export-as-type')).toBeInTheDocument(); + expect( + screen.getByLabelText('label.lineage-configuration') + ).toBeInTheDocument(); + expect(screen.getByLabelText('label.full-screen-view')).toBeInTheDocument(); + }); + + it('shows LineageSearchSelect by default in lineage mode', () => { + render(, { + wrapper: MemoryRouter, + }); + + expect(screen.getByTestId('lineage-search-select')).toBeInTheDocument(); + }); + + it('shows SearchBar when in impact analysis mode', () => { + window.location.search = '?mode=impact_analysis&depth=3&dir=downstream'; + + render(, { + wrapper: MemoryRouter, + }); + + expect(screen.getByTestId('search-bar')).toBeInTheDocument(); + }); + + it('toggles filter selection when filter button is clicked', () => { + render(, { + wrapper: MemoryRouter, + }); + + const filterButton = screen.getByLabelText('label.filter-plural'); + fireEvent.click(filterButton); + + expect(screen.getByTestId('explore-quick-filters')).toBeInTheDocument(); + }); + + it('navigates to lineage mode when lineage button is clicked', () => { + render(, { + wrapper: MemoryRouter, + }); + + const lineageButton = screen.getByText('label.lineage'); + fireEvent.click(lineageButton); + + expect(mockNavigate).toHaveBeenCalled(); + }); + + it('navigates to impact analysis mode when impact analysis button is clicked', () => { + render(, { + wrapper: MemoryRouter, + }); + + const impactAnalysisButton = screen.getByText('label.impact-analysis'); + fireEvent.click(impactAnalysisButton); + + expect(mockNavigate).toHaveBeenCalled(); + }); + + it('calls onExportClick when export button is clicked', () => { + render(, { + wrapper: MemoryRouter, + }); + + const exportButton = screen.getByLabelText('label.export-as-type'); + fireEvent.click(exportButton); + + expect(mockOnExportClick).toHaveBeenCalled(); + }); + + it('opens lineage config modal when settings button is clicked', () => { + render(, { + wrapper: MemoryRouter, + }); + + const settingsButton = screen.getByLabelText('label.lineage-configuration'); + fireEvent.click(settingsButton); + + expect(screen.getByTestId('lineage-config-modal')).toBeInTheDocument(); + }); + + it('calls onLineageConfigUpdate when modal is saved', async () => { + render(, { + wrapper: MemoryRouter, + }); + + const settingsButton = screen.getByLabelText('label.lineage-configuration'); + fireEvent.click(settingsButton); + + const saveButton = screen.getByText('Save'); + fireEvent.click(saveButton); + + await waitFor(() => { + expect(mockOnLineageConfigUpdate).toHaveBeenCalledWith(mockLineageConfig); + }); + }); + + it('toggles fullscreen mode when fullscreen button is clicked', () => { + render(, { + wrapper: MemoryRouter, + }); + + const fullscreenButton = screen.getByLabelText('label.full-screen-view'); + fireEvent.click(fullscreenButton); + + expect(mockNavigate).toHaveBeenCalled(); + }); + + it('shows node depth selector in impact analysis mode with filters active', () => { + window.location.search = '?mode=impact_analysis&depth=3&dir=downstream'; + + render(, { + wrapper: MemoryRouter, + }); + + const filterButton = screen.getByLabelText('label.filter-plural'); + fireEvent.click(filterButton); + + // Node depth should be visible in the filter section + expect( + screen.getByText( + (content) => + content?.includes('label.node-depth') && content?.includes(':') + ) + ).toBeInTheDocument(); + expect(screen.getByText('3')).toBeInTheDocument(); + }); + + it('opens node depth menu and selects new depth', () => { + window.location.search = '?mode=impact_analysis&depth=3&dir=downstream'; + + render(, { + wrapper: MemoryRouter, + }); + + const filterButton = screen.getByLabelText('label.filter-plural'); + fireEvent.click(filterButton); + + const nodeDepthButton = screen.getByText( + (content) => + content?.includes('label.node-depth') && content?.includes(':') ); + fireEvent.click(nodeDepthButton); - // check LineageSearchSelect is visible - expect(getByText('LineageSearchSelect')).toBeInTheDocument(); + // The menu items would be rendered by Material-UI Menu component + // This test verifies the click handler is set up correctly + expect(nodeDepthButton).toBeInTheDocument(); + }); - // check ExploreQuickFilters is visible - expect(getByText('ExploreQuickFilters')).toBeInTheDocument(); + it('calls onSearchValueChange when search value changes in impact analysis mode', () => { + window.location.search = '?mode=impact_analysis&depth=3&dir=downstream'; + + render(, { + wrapper: MemoryRouter, + }); + + const searchInput = screen.getByTestId('search-bar'); + fireEvent.change(searchInput, { target: { value: 'test search' } }); + + expect(mockOnSearchValueChange).toHaveBeenCalledWith('test search'); + }); + + it('shows clear filters button when filters are applied', () => { + const mockSetSelectedQuickFilters = jest.fn(); + + jest.doMock('../../../context/LineageProvider/LineageProvider', () => ({ + useLineageProvider: jest.fn().mockImplementation(() => ({ + onExportClick: mockOnExportClick, + onLineageConfigUpdate: mockOnLineageConfigUpdate, + selectedQuickFilters: [{ key: 'service', value: ['test-service'] }], + setSelectedQuickFilters: mockSetSelectedQuickFilters, + lineageConfig: mockLineageConfig, + nodes: [], + })), + })); + + render(, { + wrapper: MemoryRouter, + }); + + const filterButton = screen.getByLabelText('label.filter-plural'); + fireEvent.click(filterButton); + + expect(screen.getByText('label.clear-entity')).toBeInTheDocument(); + }); + + it('parses query parameters correctly for upstream direction', () => { + window.location.search = '?mode=lineage&depth=2&dir=upstream'; + + render(, { + wrapper: MemoryRouter, + }); + + // Component should render correctly with upstream direction + expect(screen.getByText('label.lineage')).toBeInTheDocument(); + }); + + it('handles missing query parameters with defaults', () => { + window.location.search = ''; + + render(, { + wrapper: MemoryRouter, + }); + + // Component should render with default values + expect(screen.getByText('label.lineage')).toBeInTheDocument(); + expect(screen.getByText('label.impact-analysis')).toBeInTheDocument(); }); }); diff --git a/openmetadata-ui/src/main/resources/ui/src/components/LineageTable/LineageTable.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/LineageTable/LineageTable.test.tsx index e00c3aca4b0..06e23fb51c3 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/LineageTable/LineageTable.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/LineageTable/LineageTable.test.tsx @@ -14,7 +14,6 @@ import { IconButton, Menu, ToggleButtonGroup } from '@mui/material'; import { fireEvent, render, screen, waitFor } from '@testing-library/react'; import { MemoryRouter } from 'react-router-dom'; -import { ExportTypes } from '../../constants/Export.constants'; import { useLineageProvider } from '../../context/LineageProvider/LineageProvider'; import { LineageContextType } from '../../context/LineageProvider/LineageProvider.interface'; import { EntityType } from '../../enums/entity.enum'; @@ -26,6 +25,7 @@ import { getLineagePagingData, } from '../../rest/lineageAPI'; import { useRequiredParams } from '../../utils/useRequiredParams'; +import CustomControlsComponent from '../Entity/EntityLineage/CustomControls.component'; import { LineageConfig } from '../Entity/EntityLineage/EntityLineage.interface'; import LineageTable from './LineageTable'; import { EImpactLevel } from './LineageTable.interface'; @@ -66,6 +66,9 @@ jest.mock('lodash', () => { return module; }); +jest.mock('../Entity/EntityLineage/CustomControls.component', () => { + return jest.fn().mockReturnValue(
CustomControls
); +}); const mockUseLineageProvider = useLineageProvider as jest.MockedFunction< typeof useLineageProvider @@ -163,8 +166,6 @@ const mockEntity = { domain: null, }; -// Remove the custom renderWithRouter function since our test utils handle this - describe('LineageTable', () => { beforeEach(() => { jest.clearAllMocks(); @@ -176,6 +177,7 @@ describe('LineageTable', () => { downstreamDepth: 2, upstreamDepth: 2, } as LineageConfig, + updateEntityData: jest.fn(), onExportClick: jest.fn(), onLineageConfigUpdate: jest.fn(), } as unknown as LineageContextType); @@ -230,20 +232,10 @@ describe('LineageTable', () => { }); }); - it('should render the component', () => { + it('should render the CustomControls component', () => { render(, { wrapper: MemoryRouter }); - // expect(screen.getByRole('searchbox')).toBeInTheDocument(); - expect(screen.getByText('label.lineage')).toBeInTheDocument(); - expect(screen.getByText('label.impact-analysis')).toBeInTheDocument(); - }); - - it('should display search bar with correct placeholder', () => { - render(, { wrapper: MemoryRouter }); - - const searchInput = screen.getByPlaceholderText('label.search-for-type'); - - expect(searchInput).toHaveAttribute('placeholder', 'label.search-for-type'); + expect(screen.getByText('CustomControls')).toBeInTheDocument(); }); it('should render toggle buttons for upstream and downstream', () => { @@ -263,36 +255,6 @@ describe('LineageTable', () => { expect(impactButton).toBeInTheDocument(); }); - it('should handle search input changes', async () => { - const setSearchValue = jest.fn(); - mockUseLineageTableState.mockReturnValue({ - ...defaultMockState, - setSearchValue, - }); - - render(, { wrapper: MemoryRouter }); - - const searchInput = screen.getByPlaceholderText('label.search-for-type'); - fireEvent.change(searchInput, { target: { value: 'test search' } }); - - expect(setSearchValue).toHaveBeenCalledWith('test search'); - }); - - it('should toggle filter selection when filter button is clicked', async () => { - const toggleFilterSelection = jest.fn(); - mockUseLineageTableState.mockReturnValue({ - ...defaultMockState, - toggleFilterSelection, - }); - - render(, { wrapper: MemoryRouter }); - - const filterButton = screen.getByTitle('label.filter-plural'); - fireEvent.click(filterButton); - - expect(toggleFilterSelection).toHaveBeenCalled(); - }); - it('should open impact level menu when clicked', async () => { render(, { wrapper: MemoryRouter }); @@ -337,44 +299,6 @@ describe('LineageTable', () => { expect(screen.getByText(/label.node-depth/)).toBeInTheDocument(); }); - it('should call export function when export button is clicked', async () => { - const onExportClick = jest.fn(); - mockUseLineageProvider.mockReturnValue({ - selectedQuickFilters: [], - setSelectedQuickFilters: jest.fn(), - lineageConfig: {}, - onExportClick, - onLineageConfigUpdate: jest.fn(), - } as unknown as LineageContextType); - - render(, { wrapper: MemoryRouter }); - - const exportButton = screen.getByRole('button', { name: 'Export as CSV' }); - fireEvent.click(exportButton); - - expect(onExportClick).toHaveBeenCalledWith( - [ExportTypes.CSV], - expect.any(Function) - ); - }); - - it('should open lineage config dialog when settings button is clicked', async () => { - const setDialogVisible = jest.fn(); - mockUseLineageTableState.mockReturnValue({ - ...defaultMockState, - setDialogVisible, - }); - - render(, { wrapper: MemoryRouter }); - - const settingsButton = screen.getByRole('button', { - name: 'label.lineage-configuration', - }); - fireEvent.click(settingsButton); - - expect(setDialogVisible).toHaveBeenCalledWith(true); - }); - it('should render table with correct data source for table level', () => { mockUseLineageTableState.mockReturnValue({ ...defaultMockState, @@ -405,8 +329,8 @@ describe('LineageTable', () => { render(, { wrapper: MemoryRouter }); - expect(screen.getByText('Source Table')).toBeInTheDocument(); - expect(screen.getByText('Impacted Table')).toBeInTheDocument(); + expect(screen.getByText('label.source')).toBeInTheDocument(); + expect(screen.getByText('label.impacted')).toBeInTheDocument(); }); it('should fetch nodes on component mount', async () => { @@ -503,24 +427,6 @@ describe('LineageTable', () => { expect(table).toBeInTheDocument(); }); - it('should handle node depth selection', async () => { - mockUseLineageTableState.mockReturnValue({ - ...defaultMockState, - filterSelectionActive: true, - }); - - render(, { wrapper: MemoryRouter }); - - const nodeDepthButton = screen.getByRole('button', { - name: /label.node-depth/, - }); - fireEvent.click(nodeDepthButton); - - const depthOption = await screen.findByRole('menuitem', { name: '1' }); - - expect(depthOption).toBeInTheDocument(); - }); - describe('LineageTable Hooks Integration', () => { it('should integrate with useLineageTableState correctly', () => { const mockState = { @@ -532,7 +438,12 @@ describe('LineageTable', () => { render(, { wrapper: MemoryRouter }); - expect(screen.getByDisplayValue('test search')).toBeInTheDocument(); + expect(CustomControlsComponent).toHaveBeenCalledWith( + expect.objectContaining({ + searchValue: 'test search', + }), + {} + ); }); it('should integrate with usePaging correctly', () => { diff --git a/openmetadata-ui/src/main/resources/ui/src/components/LineageTable/LineageTable.tsx b/openmetadata-ui/src/main/resources/ui/src/components/LineageTable/LineageTable.tsx index d5966a1d62f..fcbcda8b66f 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/LineageTable/LineageTable.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/LineageTable/LineageTable.tsx @@ -48,7 +48,6 @@ import { useFqn } from '../../hooks/useFqn'; import { SearchSourceAlias } from '../../interface/search.interface'; import { QueryFieldInterface } from '../../pages/ExplorePage/ExplorePage.interface'; import { - exportLineageByEntityCountAsync, getLineageByEntityCount, getLineagePagingData, } from '../../rest/lineageAPI'; @@ -306,27 +305,6 @@ const LineageTable: FC<{ entity: SourceType }> = ({ entity }) => { return JSON.stringify(query); }, [selectedQuickFilters, searchValue]); - // Function to handle export click - const handleExportClick = useCallback( - () => - exportLineageByEntityCountAsync({ - fqn: fqn ?? '', - type: entityType ?? '', - direction: lineageDirection, - nodeDepth: nodeDepth, - query_filter: queryFilter, - }), - [ - fqn, - entityType, - lineageDirection, - nodeDepth, - currentPage, - pageSize, - queryFilter, - ] - ); - // Define table columns const extraTableFilters = useMemo(() => { return ( @@ -375,7 +353,7 @@ const LineageTable: FC<{ entity: SourceType }> = ({ entity }) => { ); - }, [navigate, streamButtonGroup, impactOnEl, impactLevel, handleExportClick]); + }, [navigate, streamButtonGroup, impactOnEl, impactLevel]); // Function to fetch nodes based on current filters and pagination const fetchNodes = useCallback(async () => { @@ -662,7 +640,7 @@ const LineageTable: FC<{ entity: SourceType }> = ({ entity }) => { ), }, { - title: t('label.source-column'), + title: t('label.source-column-plural'), dataIndex: lineageDirection === LineageDirection.Downstream ? ['column', 'fromColumns'] 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 bfd2b74f344..58d2cee4538 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 @@ -1554,6 +1554,7 @@ "source": "Quelle", "source-aligned": "Source-aligned", "source-column": "Quellenspalte", + "source-column-plural": "Source Columns", "source-label": "Quelle:", "source-match": "Quellenübereinstimmung", "source-plural": "Quellen", 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 bb0b82d2eb6..80c99f5d65c 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 @@ -1554,6 +1554,7 @@ "source": "Source", "source-aligned": "Source-aligned", "source-column": "Source Column", + "source-column-plural": "Source Columns", "source-label": "Source:", "source-match": "Match By Event Source", "source-plural": "Sources", 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 4df8531432e..a89823ee32c 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 @@ -1554,6 +1554,7 @@ "source": "Fuente", "source-aligned": "Alineado con el Origen", "source-column": "Columna de Origen", + "source-column-plural": "Source Columns", "source-label": "Fuente:", "source-match": "Coincidir por Fuente de Eventos", "source-plural": "Fuentes", 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 dc46f85413d..8f77ab94303 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 @@ -1554,6 +1554,7 @@ "source": "Source", "source-aligned": "Source-aligned", "source-column": "Colonne Source", + "source-column-plural": "Source Columns", "source-label": "Source:", "source-match": "Correspondance par Source d'Événement", "source-plural": "Sources", diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/gl-es.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/gl-es.json index a8cf5733408..bd5c9990475 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/gl-es.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/gl-es.json @@ -1554,6 +1554,7 @@ "source": "Fonte", "source-aligned": "Aliñado coa fonte", "source-column": "Columna de orixe", + "source-column-plural": "Source Columns", "source-label": "Source:", "source-match": "Coincidencia por fonte de evento", "source-plural": "Fontes", 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 e7622088826..db4235184f0 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 @@ -1554,6 +1554,7 @@ "source": "מקור", "source-aligned": "מקור מתואם", "source-column": "עמודת מקור", + "source-column-plural": "Source Columns", "source-label": "Source:", "source-match": "התאמה לפי מקור אירוע", "source-plural": "מקורות", 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 ba4e585606f..e98397f9e04 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 @@ -1554,6 +1554,7 @@ "source": "ソース", "source-aligned": "ソース整列", "source-column": "ソースカラム", + "source-column-plural": "Source Columns", "source-label": "ソース:", "source-match": "イベントソースで一致", "source-plural": "ソース", diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/ko-kr.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/ko-kr.json index 39a83ae3e8f..f2efe3181a0 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/ko-kr.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/ko-kr.json @@ -1554,6 +1554,7 @@ "source": "소스", "source-aligned": "소스 정렬", "source-column": "소스 열", + "source-column-plural": "Source Columns", "source-label": "Source:", "source-match": "이벤트 소스로 매칭", "source-plural": "소스들", diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/mr-in.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/mr-in.json index f99d293dd58..5bd2e7f490c 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/mr-in.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/mr-in.json @@ -1554,6 +1554,7 @@ "source": "स्रोत", "source-aligned": "स्रोत-संरेखित", "source-column": "स्रोत स्तंभ", + "source-column-plural": "Source Columns", "source-label": "Source:", "source-match": "इव्हेंट स्रोताद्वारे जुळवा", "source-plural": "स्रोत", 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 8ad25783a86..e6a65bf05fa 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 @@ -1554,6 +1554,7 @@ "source": "Bron", "source-aligned": "Bron-georiënteerd", "source-column": "Bronkolom", + "source-column-plural": "Source Columns", "source-label": "Source:", "source-match": "Overeenkomst op eventbron", "source-plural": "Bronnen", diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/pr-pr.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/pr-pr.json index f1a8de6bdc3..22f16c120f8 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/pr-pr.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/pr-pr.json @@ -1554,6 +1554,7 @@ "source": "منبع", "source-aligned": "هم‌راستا با منبع", "source-column": "ستون منبع", + "source-column-plural": "Source Columns", "source-label": "Source:", "source-match": "مطابقت بر اساس منبع رویداد", "source-plural": "منابع", 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 6fa5152f551..8be746398ea 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 @@ -1554,6 +1554,7 @@ "source": "Fonte", "source-aligned": "Alinhado à Fonte", "source-column": "Coluna de Fonte", + "source-column-plural": "Source Columns", "source-label": "Source:", "source-match": "Correspondência por Fonte de Evento", "source-plural": "Fontes", diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/pt-pt.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/pt-pt.json index b89004744d8..2d1a6f84891 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/pt-pt.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/pt-pt.json @@ -1554,6 +1554,7 @@ "source": "Fonte", "source-aligned": "Alinhado à Fonte", "source-column": "Coluna de Fonte", + "source-column-plural": "Source Columns", "source-label": "Source:", "source-match": "Correspondência por Fonte de Evento", "source-plural": "Fontes", 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 1249ff090ee..664b8e49e95 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 @@ -1554,6 +1554,7 @@ "source": "Источник", "source-aligned": "Выровненный по источнику", "source-column": "Источник столбца", + "source-column-plural": "Source Columns", "source-label": "Source:", "source-match": "Сопоставление по источнику события", "source-plural": "Источники", diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/th-th.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/th-th.json index 04e0a802333..0c0e4bb5095 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/th-th.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/th-th.json @@ -1554,6 +1554,7 @@ "source": "แหล่งที่มา", "source-aligned": "ตรงตามแหล่งที่มา", "source-column": "คอลัมน์แหล่งที่มา", + "source-column-plural": "Source Columns", "source-label": "Source:", "source-match": "จับคู่ตามแหล่งที่มาของเหตุการณ์", "source-plural": "แหล่งที่มาหลายรายการ", diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/tr-tr.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/tr-tr.json index 2416772079c..49e26073089 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/tr-tr.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/tr-tr.json @@ -1554,6 +1554,7 @@ "source": "Kaynak", "source-aligned": "Kaynak Odaklı", "source-column": "Kaynak Sütun", + "source-column-plural": "Source Columns", "source-label": "Source:", "source-match": "Olay Kaynağına Göre Eşleştir", "source-plural": "Kaynaklar", 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 47bc3ab0ffa..52e40e67c02 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 @@ -1554,6 +1554,7 @@ "source": "源", "source-aligned": "Source-aligned", "source-column": "源列", + "source-column-plural": "Source Columns", "source-label": "Source:", "source-match": "根据事件源匹配", "source-plural": "来源", diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/zh-tw.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/zh-tw.json index 97267de2e4b..e11d781e107 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/zh-tw.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/zh-tw.json @@ -1554,6 +1554,7 @@ "source": "來源", "source-aligned": "來源導向", "source-column": "來源欄位", + "source-column-plural": "Source Columns", "source-label": "來源:", "source-match": "依事件來源比對", "source-plural": "來源",