Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
b2ee2a7
fix: use historical column snapshot in table version view
miantalha45 Apr 17, 2026
e5bb63c
Merge branch 'main' into table-history-issue
miantalha45 Apr 17, 2026
3a523f0
Merge branch 'main' into table-history-issue
miantalha45 Apr 17, 2026
b76028b
Merge branch 'main' into table-history-issue
miantalha45 Apr 17, 2026
0bc5ac7
fix paging issue
miantalha45 Apr 17, 2026
d4475c5
Merge branch 'main' into table-history-issue
miantalha45 Apr 19, 2026
2c4882f
Merge branch 'main' into table-history-issue
miantalha45 Apr 20, 2026
640ab1a
Fix github suggestions
miantalha45 Apr 20, 2026
c8fc9f4
Merge branch 'main' into table-history-issue
miantalha45 Apr 20, 2026
b5d3ddf
fix copilot suggestions
miantalha45 Apr 20, 2026
321ecb3
Merge branch 'main' into table-history-issue
miantalha45 Apr 20, 2026
587d905
Merge branch 'main' into table-history-issue
miantalha45 Apr 21, 2026
4cee579
Merge branch 'main' into table-history-issue
miantalha45 Apr 22, 2026
5e1e688
Merge branch 'main' into table-history-issue
miantalha45 Apr 23, 2026
ac888bf
Merge branch 'main' into table-history-issue
miantalha45 Apr 23, 2026
d476859
Merge branch 'main' into table-history-issue
miantalha45 Apr 24, 2026
8bc459a
Merge branch 'main' into table-history-issue
miantalha45 Apr 24, 2026
915a833
Merge branch 'main' into table-history-issue
miantalha45 Apr 24, 2026
5b3a4b7
Merge branch 'main' into table-history-issue
miantalha45 Apr 25, 2026
10edf3c
Merge branch 'main' into table-history-issue
miantalha45 Apr 25, 2026
e8c7731
Merge branch 'main' into table-history-issue
miantalha45 Apr 26, 2026
0538240
Merge branch 'main' into table-history-issue
miantalha45 Apr 28, 2026
89759d0
Merge branch 'main' into table-history-issue
miantalha45 May 2, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,6 @@ import {
import { Operation } from '../../../generated/entity/policies/policy';
import { TagSource } from '../../../generated/type/tagLabel';
import { usePaging } from '../../../hooks/paging/usePaging';
import { useFqn } from '../../../hooks/useFqn';
import {
getTableColumnsByFQN,
searchTableColumnsByFQN,
} from '../../../rest/tableAPI';
import { getPartialNameFromTableFQN } from '../../../utils/CommonUtils';
import {
getColumnsDataWithVersionChanges,
Expand All @@ -45,6 +40,7 @@ import {
getEntityVersionByField,
getEntityVersionTags,
} from '../../../utils/EntityVersionUtils';
import { searchInColumns } from '../../../utils/EntityUtils';
import { getPrioritizedViewPermission } from '../../../utils/PermissionsUtils';
import { getVersionPath } from '../../../utils/RouterUtils';
import { pruneEmptyChildren } from '../../../utils/TableUtils';
Expand Down Expand Up @@ -89,56 +85,24 @@ const TableVersion: React.FC<TableVersionProp> = ({
paging,
handlePagingChange,
} = usePaging(PAGE_SIZE_LARGE);
const { fqn: tableFqn } = useFqn();
const [searchText, setSearchText] = useState('');
// Pagination state for columns
const [tableColumns, setTableColumns] = useState<Column[]>([]);
const [columnsLoading, setColumnsLoading] = useState(true); // Start with loading state
const columnsLoading = isVersionLoading;
const [changeDescription, setChangeDescription] = useState<ChangeDescription>(
currentVersionData.changeDescription as ChangeDescription
);

// Function to fetch paginated columns or search results
const fetchPaginatedColumns = useCallback(
async (page = 1, searchQuery?: string) => {
if (!tableFqn) {
return;
}
const allHistoricalColumns = useMemo(
() => pruneEmptyChildren(currentVersionData.columns) ?? [],
[currentVersionData.columns]
);

setColumnsLoading(true);
try {
const offset = (page - 1) * pageSize;
const filteredHistoricalColumns = useMemo(() => {
if (!searchText) {
return allHistoricalColumns;
}

// Use search API if there's a search query, otherwise use regular pagination
const response = searchQuery
? await searchTableColumnsByFQN(tableFqn, {
q: searchQuery,
limit: pageSize,
offset: offset,
fields: 'tags',
})
: await getTableColumnsByFQN(tableFqn, {
limit: pageSize,
offset: offset,
fields: 'tags',
});

setTableColumns(pruneEmptyChildren(response.data) || []);
handlePagingChange(response.paging);
} catch {
// Set empty state if API fails
setTableColumns([]);
handlePagingChange({
offset: 1,
limit: pageSize,
total: 0,
});
} finally {
setColumnsLoading(false);
}
},
[tableFqn, pageSize]
);
return searchInColumns(allHistoricalColumns, searchText);
}, [allHistoricalColumns, searchText]);
Comment on lines +99 to +105
Copy link

Copilot AI Apr 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

filteredHistoricalColumns only matches on top-level name and description, and it is not recursive. This changes search behavior vs VersionTable’s searchInColumns (which searches displayName, dataType, and children). Consider reusing the same searchInColumns logic (or an equivalent recursive filter) for the full historical column tree before slicing, so nested/typed matches aren’t dropped.

Copilot uses AI. Check for mistakes.
Comment on lines +99 to +105
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

VersionTable already performs local column filtering based on its own searchText state, and this component now filters again via filteredHistoricalColumns. This duplicates work and can cause brief UI inconsistency (e.g., user types a search term and the child filters the current page slice before the parent updates pagination/slice). Consider making a single source of truth for filtering—either let TableVersion own search + pagination and disable the internal filtering in VersionTable for this usage, or pass the full (unfiltered) columns to VersionTable and let it handle filtering while TableVersion only handles pagination totals/offsets.

Copilot uses AI. Check for mistakes.

const handleSearchAction = useCallback(
(searchValue: string) => {
Expand All @@ -150,18 +114,17 @@ const TableVersion: React.FC<TableVersionProp> = ({

const handleColumnsPageChange = useCallback(
({ currentPage }: PagingHandlerParams) => {
fetchPaginatedColumns(currentPage, searchText);
handlePageChange(currentPage);
},
[paging, fetchPaginatedColumns, searchText]
[handlePageChange]
);

const paginationProps = useMemo(
() => ({
currentPage,
showPagination,
isLoading: columnsLoading,
isNumberBased: Boolean(searchText),
isNumberBased: true,
pageSize,
paging,
pagingHandler: handleColumnsPageChange,
Expand All @@ -171,7 +134,6 @@ const TableVersion: React.FC<TableVersionProp> = ({
currentPage,
showPagination,
columnsLoading,
searchText,
pageSize,
paging,
handleColumnsPageChange,
Expand All @@ -196,10 +158,17 @@ const TableVersion: React.FC<TableVersionProp> = ({
[changeDescription, owners, tier, domains]
);

const columns = useMemo(() => {
const colList = cloneDeep(tableColumns);
const tableColumns = useMemo(() => {
const offset = (currentPage - 1) * pageSize;

return filteredHistoricalColumns.slice(offset, offset + pageSize);
}, [filteredHistoricalColumns, currentPage, pageSize]);

return getColumnsDataWithVersionChanges<Column>(changeDescription, colList);
const columns = useMemo(() => {
return getColumnsDataWithVersionChanges<Column>(
changeDescription,
cloneDeep(tableColumns)
);
}, [tableColumns, changeDescription]);
Comment on lines +161 to 172
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getColumnsDataWithVersionChanges() can inject added/deleted columns into the provided list (e.g., deleted columns are unshifted via addDeletedColumnsDiff). Because pagination (slice) is done before applying version diffs, deleted/added columns may never be visible (or may appear on the wrong page) and page sizing can become inconsistent. Consider applying version changes to the full historical column list first, then performing search filtering and finally slicing for pagination.

Copilot uses AI. Check for mistakes.

const handleTabChange = (activeKey: string) => {
Expand Down Expand Up @@ -355,20 +324,17 @@ const TableVersion: React.FC<TableVersionProp> = ({
]
);

// Fetch columns when search changes
useEffect(() => {
if (tableFqn && !isVersionLoading) {
// Reset to first page when search changes
fetchPaginatedColumns(currentPage, searchText || undefined);
if (isVersionLoading) {
return;
}
}, [
isVersionLoading,
tableFqn,
searchText,
fetchPaginatedColumns,
pageSize,
currentPage,
]);
const offset = (currentPage - 1) * pageSize;
handlePagingChange({
offset,
limit: pageSize,
total: filteredHistoricalColumns.length,
});
}, [isVersionLoading, filteredHistoricalColumns, currentPage, pageSize, handlePagingChange]);
Comment on lines 327 to +337
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tableColumns and the paging totals are only populated in a useEffect, so the first paint after isVersionLoading becomes false can render an empty VersionTable (and showPagination may be wrong) for one render cycle. To avoid a visible empty-state flash, initialize the paginated columns/paging synchronously (e.g., compute the slice in a useMemo and pass it directly, or initialize state from currentVersionData.columns, or switch this effect to useLayoutEffect).

Copilot uses AI. Check for mistakes.

return (
<>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,14 @@
*/

import { act, fireEvent, render, screen } from '@testing-library/react';
import { DataType } from '../../../generated/entity/data/table';
import { ENTITY_PERMISSIONS } from '../../../mocks/Permissions.mock';
import { tableVersionMockProps } from '../../../mocks/TableVersion.mock';
import {
mockTableData,
tableVersionMockProps,
} from '../../../mocks/TableVersion.mock';
import TableVersion from './TableVersion.component';
import VersionTable from '../../Entity/VersionTable/VersionTable.component';

const mockNavigate = jest.fn();
jest.mock(
Expand Down Expand Up @@ -138,6 +143,50 @@ describe('TableVersion tests', () => {
);
});

it('should pass historical columns from currentVersionData to VersionTable, not from a live API call', async () => {
const historicalVersionData = {
...mockTableData,
columns: [
{
name: 'order_amount',
dataType: DataType.Decimal,
dataTypeDisplay: 'decimal(9,1)',
precision: 9,
scale: 1,
fullyQualifiedName:
'sample_data.ecommerce_db.shopify.raw_product_catalog.order_amount',
tags: [],
ordinalPosition: 1,
},
],
changeDescription: {
fieldsAdded: [],
fieldsUpdated: [],
fieldsDeleted: [],
previousVersion: 0.1,
},
};

const mockedVersionTable = VersionTable as jest.MockedFunction<typeof VersionTable>;
mockedVersionTable.mockClear();

await act(async () => {
render(
<TableVersion
{...tableVersionMockProps}
currentVersionData={historicalVersionData}
/>
);
});

const calls = mockedVersionTable.mock.calls;
expect(calls.length).toBeGreaterThan(0);
const columnsPassedToVersionTable = calls[calls.length - 1][0].columns;

expect(columnsPassedToVersionTable).toHaveLength(1);
expect(columnsPassedToVersionTable[0].dataTypeDisplay).toBe('decimal(9,1)');
});

describe('ViewCustomFields Permission Tests', () => {
it('should render custom properties tab when ViewCustomFields is true', async () => {
await act(async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,14 @@ function VersionTable<T extends Column | SearchIndexField>({
const [expandedRowKeys, setExpandedRowKeys] = useState<string[]>([]);

const data = useMemo(() => {
if (searchText) {
if (searchText && !handelSearchCallback) {
const searchCols = searchInColumns<T>(columns, searchText);

return makeData<T>(searchCols);
} else {
return makeData<T>(columns);
}
}, [searchText, columns]);

return makeData<T>(columns);
}, [searchText, columns, handelSearchCallback]);
Comment on lines +61 to +68
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The prop name handelSearchCallback appears to be a typo ("handel" vs "handle"). Since it’s now part of the core search/pagination flow, consider renaming it to handleSearchCallback (optionally keeping handelSearchCallback as a deprecated alias) to avoid spreading the misspelling.

Copilot uses AI. Check for mistakes.

const renderColumnName = useCallback(
(name: T['name'], record: T) => {
Expand Down
Loading