mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-08-17 21:46:50 +00:00
fix lineage child node column name not taking remaining space in card and showMoreButton (#21473)
* fix lineage child node column name not taking remaning space in card * fix the showColumn button which was apperaring even if there were no columns
This commit is contained in:
parent
4c96b85a47
commit
bb54555daa
@ -137,8 +137,7 @@ export const getColumnContent = (
|
||||
<div
|
||||
className={classNames(
|
||||
'custom-node-column-container',
|
||||
isColumnTraced && 'custom-node-header-tracing',
|
||||
showDataObservabilitySummary && 'p-r-md'
|
||||
isColumnTraced && 'custom-node-header-tracing'
|
||||
)}
|
||||
data-testid={`column-${fullyQualifiedName}`}
|
||||
key={fullyQualifiedName}
|
||||
@ -152,16 +151,16 @@ export const getColumnContent = (
|
||||
'lineage-column-node-handle',
|
||||
encodeLineageHandles(fullyQualifiedName ?? '')
|
||||
)}
|
||||
<Row gutter={24}>
|
||||
<Col
|
||||
className="custom-node-name-container"
|
||||
span={showDataObservabilitySummary ? 8 : 12}>
|
||||
<Row className="d-flex items-center" gutter={12}>
|
||||
<Col className="custom-node-name-container" flex="1">
|
||||
{column.dataType && (
|
||||
<div className="custom-node-name-icon">
|
||||
{getColumnDataTypeIcon({
|
||||
dataType: column.dataType,
|
||||
width: '14px',
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
<Typography.Text
|
||||
className="custom-node-column-label"
|
||||
ellipsis={{ tooltip: true }}>
|
||||
@ -169,16 +168,18 @@ export const getColumnContent = (
|
||||
</Typography.Text>
|
||||
</Col>
|
||||
|
||||
{column.constraint && (
|
||||
<Col
|
||||
className={classNames(
|
||||
'custom-node-constraint',
|
||||
showDataObservabilitySummary ? 'text-left' : 'text-right'
|
||||
)}
|
||||
span={showDataObservabilitySummary ? 8 : 12}>
|
||||
flex="80px">
|
||||
{column.constraint}
|
||||
</Col>
|
||||
)}
|
||||
{showDataObservabilitySummary && (
|
||||
<Col span={8}>
|
||||
<Col flex="80px">
|
||||
<TestSuiteSummaryWidget
|
||||
isLoading={isLoading}
|
||||
size="small"
|
||||
|
@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright 2025 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 { useLineageProvider } from '../../../../context/LineageProvider/LineageProvider';
|
||||
import { EntityType } from '../../../../enums/entity.enum';
|
||||
import { LineageLayer } from '../../../../generated/settings/settings';
|
||||
import NodeChildren from './NodeChildren.component';
|
||||
|
||||
const mockNode = {
|
||||
id: 'test-id',
|
||||
entityType: EntityType.TABLE,
|
||||
fullyQualifiedName: 'test.fqn',
|
||||
name: 'test',
|
||||
columns: [
|
||||
{
|
||||
name: 'column1',
|
||||
fullyQualifiedName: 'test.fqn.column1',
|
||||
dataType: 'STRING',
|
||||
},
|
||||
{
|
||||
name: 'column2',
|
||||
fullyQualifiedName: 'test.fqn.column2',
|
||||
dataType: 'STRING',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const mockLineageProvider = {
|
||||
tracedColumns: [],
|
||||
activeLayer: [LineageLayer.ColumnLevelLineage],
|
||||
onColumnClick: jest.fn(),
|
||||
columnsHavingLineage: ['test.fqn.column1'],
|
||||
isEditMode: false,
|
||||
expandAllColumns: false,
|
||||
};
|
||||
|
||||
jest.mock('../../../../context/LineageProvider/LineageProvider', () => ({
|
||||
useLineageProvider: jest.fn().mockImplementation(() => mockLineageProvider),
|
||||
}));
|
||||
|
||||
jest.mock('../../../../rest/testAPI', () => ({
|
||||
getTestCaseExecutionSummary: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('../../../../utils/EntityLink', () => ({
|
||||
EntityLink: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('../../../../utils/SearchClassBase', () => ({
|
||||
getEntityIcon: jest.fn().mockReturnValue('entityIcon'),
|
||||
}));
|
||||
|
||||
jest.mock('../CustomNode.utils', () => ({
|
||||
getColumnContent: jest
|
||||
.fn()
|
||||
.mockImplementation((column) => <p>{column.name}</p>),
|
||||
}));
|
||||
|
||||
jest.mock('../TestSuiteSummaryWidget/TestSuiteSummaryWidget.component', () =>
|
||||
jest.fn().mockReturnValue(<p>TestSuiteSummaryWidget</p>)
|
||||
);
|
||||
|
||||
describe('NodeChildren Component', () => {
|
||||
it('should show show more button when there are columns without lineage', () => {
|
||||
render(<NodeChildren isConnectable={false} node={mockNode} />);
|
||||
|
||||
const showMoreButton = screen.getByTestId('show-more-columns-btn');
|
||||
|
||||
expect(showMoreButton).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should hide show more button when all columns are shown after clicking show more button', () => {
|
||||
render(<NodeChildren isConnectable={false} node={mockNode} />);
|
||||
|
||||
const showMoreButton = screen.getByTestId('show-more-columns-btn');
|
||||
fireEvent.click(showMoreButton);
|
||||
|
||||
expect(
|
||||
screen.queryByTestId('show-more-columns-btn')
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should hide show more button when all columns are shown', () => {
|
||||
(useLineageProvider as jest.Mock).mockImplementation(() => ({
|
||||
...mockLineageProvider,
|
||||
columnsHavingLineage: ['test.fqn.column1', 'test.fqn.column2'],
|
||||
}));
|
||||
|
||||
render(<NodeChildren isConnectable={false} node={mockNode} />);
|
||||
|
||||
expect(
|
||||
screen.queryByTestId('show-more-columns-btn')
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should show all columns when searching', () => {
|
||||
render(<NodeChildren isConnectable={false} node={mockNode} />);
|
||||
|
||||
const searchInput = screen.getByPlaceholderText('label.search-entity');
|
||||
act(() => {
|
||||
fireEvent.change(searchInput, { target: { value: 'column' } });
|
||||
});
|
||||
|
||||
expect(screen.getByText('column1')).toBeInTheDocument();
|
||||
expect(screen.getByText('column2')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should hide show more button when searching', () => {
|
||||
render(<NodeChildren isConnectable={false} node={mockNode} />);
|
||||
|
||||
const searchInput = screen.getByPlaceholderText('label.search-entity');
|
||||
fireEvent.change(searchInput, { target: { value: 'column' } });
|
||||
|
||||
expect(
|
||||
screen.queryByTestId('show-more-columns-btn')
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should filter columns based on search input', () => {
|
||||
render(<NodeChildren isConnectable={false} node={mockNode} />);
|
||||
|
||||
const searchInput = screen.getByPlaceholderText('label.search-entity');
|
||||
fireEvent.change(searchInput, { target: { value: 'column1' } });
|
||||
|
||||
expect(screen.getByText('column1')).toBeInTheDocument();
|
||||
expect(screen.queryByText('column2')).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
@ -115,6 +115,7 @@ const NodeChildren = ({ node, isConnectable }: NodeChildrenProps) => {
|
||||
getEntityName(column).toLowerCase().includes(value.toLowerCase())
|
||||
);
|
||||
setFilteredColumns(filtered);
|
||||
setShowAllColumns(true);
|
||||
}
|
||||
},
|
||||
[children]
|
||||
@ -151,7 +152,7 @@ const NodeChildren = ({ node, isConnectable }: NodeChildrenProps) => {
|
||||
try {
|
||||
const response = await getTestCaseExecutionSummary(testSuite.id);
|
||||
setSummary(response);
|
||||
} catch (error) {
|
||||
} catch {
|
||||
setSummary(undefined);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
@ -286,7 +287,9 @@ const NodeChildren = ({ node, isConnectable }: NodeChildrenProps) => {
|
||||
|
||||
// Pre-render column data outside of the return statement
|
||||
const renderedColumns = useMemo(() => {
|
||||
return filteredColumns.map((column) => renderColumnsData(column as Column));
|
||||
return filteredColumns
|
||||
.map((column) => renderColumnsData(column as Column))
|
||||
.filter(Boolean);
|
||||
}, [filteredColumns, renderColumnsData]);
|
||||
|
||||
// Memoize the expand/collapse icon to prevent unnecessary re-renders
|
||||
@ -303,6 +306,15 @@ const NodeChildren = ({ node, isConnectable }: NodeChildrenProps) => {
|
||||
return searchClassBase.getEntityIcon(node.entityType ?? '');
|
||||
}, [node.entityType]);
|
||||
|
||||
const shouldShowMoreButton = useMemo(() => {
|
||||
return (
|
||||
!showAllColumns &&
|
||||
!isEmpty(children) &&
|
||||
renderedColumns.length !== children.length &&
|
||||
!searchValue
|
||||
);
|
||||
}, [showAllColumns, children, renderedColumns, searchValue]);
|
||||
|
||||
// Memoize the expand/collapse click handler
|
||||
const handleExpandCollapseClick = useCallback((e: React.MouseEvent) => {
|
||||
e.stopPropagation();
|
||||
@ -346,6 +358,7 @@ const NodeChildren = ({ node, isConnectable }: NodeChildrenProps) => {
|
||||
/>
|
||||
</div>
|
||||
|
||||
{!isEmpty(renderedColumns) && (
|
||||
<section className="m-t-md" id="table-columns">
|
||||
<div
|
||||
className={classNames('rounded-4 overflow-hidden', {
|
||||
@ -354,10 +367,12 @@ const NodeChildren = ({ node, isConnectable }: NodeChildrenProps) => {
|
||||
{renderedColumns}
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
|
||||
{!showAllColumns && (
|
||||
{shouldShowMoreButton && (
|
||||
<Button
|
||||
className="m-t-xs text-primary"
|
||||
data-testid="show-more-columns-btn"
|
||||
type="text"
|
||||
onClick={handleShowMoreClick}>
|
||||
{t('label.show-more-entity', {
|
||||
|
@ -78,6 +78,7 @@
|
||||
|
||||
.column-container {
|
||||
min-height: 48px;
|
||||
max-width: 320px;
|
||||
padding: 12px;
|
||||
background-color: @grey-1;
|
||||
|
||||
@ -284,16 +285,17 @@
|
||||
}
|
||||
|
||||
.custom-node-column-container {
|
||||
padding: 6px;
|
||||
padding: 6px 8px;
|
||||
background: @white;
|
||||
position: relative;
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
|
||||
.custom-node-name-container {
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-left: 12px;
|
||||
text-align: left;
|
||||
gap: 4px;
|
||||
|
||||
.custom-node-name-icon {
|
||||
@ -302,7 +304,8 @@
|
||||
}
|
||||
|
||||
.custom-node-column-label {
|
||||
max-width: 140px;
|
||||
width: 100%;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -92,12 +92,6 @@
|
||||
.w-11-12 {
|
||||
width: 91.666667%;
|
||||
}
|
||||
.w-min-0 {
|
||||
min-width: 0;
|
||||
}
|
||||
.w-max-full {
|
||||
max-width: 100%;
|
||||
}
|
||||
.w-max-20 {
|
||||
max-width: 20%;
|
||||
}
|
||||
@ -191,6 +185,9 @@
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
.w-min-0 {
|
||||
min-width: 0;
|
||||
}
|
||||
.w-min-10 {
|
||||
min-width: 10rem;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user