mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-12-16 10:08:08 +00:00
This reverts commit 73eb1fd0d9c19f86960f83375701fb05c68be467.
This commit is contained in:
parent
dc125b67a4
commit
1ca4329483
@ -1029,7 +1029,9 @@ test.describe('Glossary tests', () => {
|
|||||||
|
|
||||||
await selectActiveGlossary(page, glossary2.data.displayName);
|
await selectActiveGlossary(page, glossary2.data.displayName);
|
||||||
|
|
||||||
const termRes = page.waitForResponse('/api/v1/glossaryTerms?*');
|
const termRes = page.waitForResponse(
|
||||||
|
'/api/v1/glossaryTerms?directChildrenOf=*&fields=childrenCount%2Cowners%2Creviewers&limit=1000'
|
||||||
|
);
|
||||||
// verify the term is moved to the destination glossary
|
// verify the term is moved to the destination glossary
|
||||||
await page.getByTestId('expand-collapse-all-button').click();
|
await page.getByTestId('expand-collapse-all-button').click();
|
||||||
await termRes;
|
await termRes;
|
||||||
@ -1242,7 +1244,9 @@ test.describe('Glossary tests', () => {
|
|||||||
await selectActiveGlossaryTerm(page, glossaryTerm1.data.displayName);
|
await selectActiveGlossaryTerm(page, glossaryTerm1.data.displayName);
|
||||||
await page.getByTestId('terms').click();
|
await page.getByTestId('terms').click();
|
||||||
|
|
||||||
const termRes = page.waitForResponse('/api/v1/glossaryTerms?*');
|
const termRes = page.waitForResponse(
|
||||||
|
'/api/v1/glossaryTerms?directChildrenOf=*&fields=childrenCount%2Cowners%2Creviewers&limit=1000'
|
||||||
|
);
|
||||||
await page.getByTestId('expand-collapse-all-button').click();
|
await page.getByTestId('expand-collapse-all-button').click();
|
||||||
await termRes;
|
await termRes;
|
||||||
|
|
||||||
@ -1436,7 +1440,9 @@ test.describe('Glossary tests', () => {
|
|||||||
await sidebarClick(page, SidebarItem.GLOSSARY);
|
await sidebarClick(page, SidebarItem.GLOSSARY);
|
||||||
await selectActiveGlossary(page, glossary1.data.displayName);
|
await selectActiveGlossary(page, glossary1.data.displayName);
|
||||||
|
|
||||||
const termRes = page.waitForResponse('/api/v1/glossaryTerms?*');
|
const termRes = page.waitForResponse(
|
||||||
|
'/api/v1/glossaryTerms?directChildrenOf=*&fields=childrenCount%2Cowners%2Creviewers&limit=1000'
|
||||||
|
);
|
||||||
await page.getByTestId('expand-collapse-all-button').click();
|
await page.getByTestId('expand-collapse-all-button').click();
|
||||||
await termRes;
|
await termRes;
|
||||||
|
|
||||||
|
|||||||
@ -63,7 +63,7 @@ import {
|
|||||||
} from '../../../constants/Glossary.contant';
|
} from '../../../constants/Glossary.contant';
|
||||||
import { TABLE_CONSTANTS } from '../../../constants/Teams.constants';
|
import { TABLE_CONSTANTS } from '../../../constants/Teams.constants';
|
||||||
import { ERROR_PLACEHOLDER_TYPE } from '../../../enums/common.enum';
|
import { ERROR_PLACEHOLDER_TYPE } from '../../../enums/common.enum';
|
||||||
import { EntityType, TabSpecificField } from '../../../enums/entity.enum';
|
import { EntityType } from '../../../enums/entity.enum';
|
||||||
import { ResolveTask } from '../../../generated/api/feed/resolveTask';
|
import { ResolveTask } from '../../../generated/api/feed/resolveTask';
|
||||||
import {
|
import {
|
||||||
EntityReference,
|
EntityReference,
|
||||||
@ -83,7 +83,6 @@ import { getAllFeeds, updateTask } from '../../../rest/feedsAPI';
|
|||||||
import {
|
import {
|
||||||
getFirstLevelGlossaryTermsPaginated,
|
getFirstLevelGlossaryTermsPaginated,
|
||||||
getGlossaryTermChildrenLazy,
|
getGlossaryTermChildrenLazy,
|
||||||
getGlossaryTerms,
|
|
||||||
GlossaryTermWithChildren,
|
GlossaryTermWithChildren,
|
||||||
patchGlossaryTerm,
|
patchGlossaryTerm,
|
||||||
searchGlossaryTermsPaginated,
|
searchGlossaryTermsPaginated,
|
||||||
@ -96,8 +95,8 @@ import {
|
|||||||
} from '../../../utils/EntityUtils';
|
} from '../../../utils/EntityUtils';
|
||||||
import Fqn from '../../../utils/Fqn';
|
import Fqn from '../../../utils/Fqn';
|
||||||
import {
|
import {
|
||||||
buildTree,
|
|
||||||
findExpandableKeysForArray,
|
findExpandableKeysForArray,
|
||||||
|
getAllExpandableKeys,
|
||||||
glossaryTermTableColumnsWidth,
|
glossaryTermTableColumnsWidth,
|
||||||
permissionForApproveOrReject,
|
permissionForApproveOrReject,
|
||||||
StatusClass,
|
StatusClass,
|
||||||
@ -177,13 +176,7 @@ const GlossaryTermTab = ({ isGlossary, className }: GlossaryTermTabProps) => {
|
|||||||
>(undefined);
|
>(undefined);
|
||||||
const [searchTerm, setSearchTerm] = useState('');
|
const [searchTerm, setSearchTerm] = useState('');
|
||||||
const [searchInput, setSearchInput] = useState('');
|
const [searchInput, setSearchInput] = useState('');
|
||||||
const [searchPaging, setSearchPaging] = useState<{
|
|
||||||
offset: number;
|
|
||||||
total?: number;
|
|
||||||
hasMore: boolean;
|
|
||||||
}>({ offset: 0, total: undefined, hasMore: true });
|
|
||||||
const [isExpandingAll, setIsExpandingAll] = useState(false);
|
const [isExpandingAll, setIsExpandingAll] = useState(false);
|
||||||
const [toggleExpandBtn, setToggleExpandBtn] = useState(false);
|
|
||||||
|
|
||||||
const { ref: infiniteScrollRef, inView } = useInView({
|
const { ref: infiniteScrollRef, inView } = useInView({
|
||||||
threshold: 0.1,
|
threshold: 0.1,
|
||||||
@ -199,6 +192,7 @@ const GlossaryTermTab = ({ isGlossary, className }: GlossaryTermTabProps) => {
|
|||||||
|
|
||||||
const fetchChildTerms = async (parentFQN: string) => {
|
const fetchChildTerms = async (parentFQN: string) => {
|
||||||
setLoadingChildren((prev) => ({ ...prev, [parentFQN]: true }));
|
setLoadingChildren((prev) => ({ ...prev, [parentFQN]: true }));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { data } = await getGlossaryTermChildrenLazy(parentFQN, 1000); // Get all children
|
const { data } = await getGlossaryTermChildrenLazy(parentFQN, 1000); // Get all children
|
||||||
|
|
||||||
@ -245,11 +239,7 @@ const GlossaryTermTab = ({ isGlossary, className }: GlossaryTermTabProps) => {
|
|||||||
const fetchAllTerms = async (loadMore = false) => {
|
const fetchAllTerms = async (loadMore = false) => {
|
||||||
if (!loadMore) {
|
if (!loadMore) {
|
||||||
setIsTableLoading(true);
|
setIsTableLoading(true);
|
||||||
if (searchTerm) {
|
handlePagingChange((prev) => ({ ...prev, after: undefined }));
|
||||||
setSearchPaging({ offset: 0, total: undefined, hasMore: true });
|
|
||||||
} else {
|
|
||||||
handlePagingChange((prev) => ({ ...prev, after: undefined }));
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
setIsLoadingMore(true);
|
setIsLoadingMore(true);
|
||||||
}
|
}
|
||||||
@ -260,7 +250,7 @@ const GlossaryTermTab = ({ isGlossary, className }: GlossaryTermTabProps) => {
|
|||||||
|
|
||||||
// Use search API if search term is present
|
// Use search API if search term is present
|
||||||
if (searchTerm) {
|
if (searchTerm) {
|
||||||
const currentOffset = loadMore ? searchPaging.offset : 0;
|
const offset = loadMore && paging.after ? parseInt(paging.after) : 0;
|
||||||
const response = await searchGlossaryTermsPaginated(
|
const response = await searchGlossaryTermsPaginated(
|
||||||
searchTerm,
|
searchTerm,
|
||||||
undefined,
|
undefined,
|
||||||
@ -268,23 +258,11 @@ const GlossaryTermTab = ({ isGlossary, className }: GlossaryTermTabProps) => {
|
|||||||
undefined,
|
undefined,
|
||||||
undefined,
|
undefined,
|
||||||
PAGE_SIZE_LARGE,
|
PAGE_SIZE_LARGE,
|
||||||
currentOffset,
|
offset,
|
||||||
'children,relatedTerms,reviewers,owners,tags,usageCount,domains,extension,childrenCount'
|
'children,relatedTerms,reviewers,owners,tags,usageCount,domains,extension,childrenCount'
|
||||||
);
|
);
|
||||||
data = response.data;
|
data = response.data;
|
||||||
pagingResponse = response.paging;
|
pagingResponse = response.paging;
|
||||||
|
|
||||||
// Update search pagination state
|
|
||||||
const newOffset = currentOffset + PAGE_SIZE_LARGE;
|
|
||||||
const hasMore =
|
|
||||||
data.length === PAGE_SIZE_LARGE &&
|
|
||||||
(pagingResponse?.total === undefined ||
|
|
||||||
newOffset < pagingResponse?.total);
|
|
||||||
setSearchPaging({
|
|
||||||
offset: newOffset,
|
|
||||||
total: pagingResponse?.total,
|
|
||||||
hasMore,
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
// Use regular listing API when no search term
|
// Use regular listing API when no search term
|
||||||
const response = await getFirstLevelGlossaryTermsPaginated(
|
const response = await getFirstLevelGlossaryTermsPaginated(
|
||||||
@ -294,13 +272,6 @@ const GlossaryTermTab = ({ isGlossary, className }: GlossaryTermTabProps) => {
|
|||||||
);
|
);
|
||||||
data = response.data;
|
data = response.data;
|
||||||
pagingResponse = response.paging;
|
pagingResponse = response.paging;
|
||||||
|
|
||||||
// Update regular paging state for next page
|
|
||||||
handlePagingChange((prev) => ({
|
|
||||||
...prev,
|
|
||||||
after: pagingResponse?.after,
|
|
||||||
total: pagingResponse?.total || prev.total,
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!data || !Array.isArray(data)) {
|
if (!data || !Array.isArray(data)) {
|
||||||
@ -320,6 +291,13 @@ const GlossaryTermTab = ({ isGlossary, className }: GlossaryTermTabProps) => {
|
|||||||
// Start with all terms collapsed
|
// Start with all terms collapsed
|
||||||
setExpandedRowKeys([]);
|
setExpandedRowKeys([]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update paging state for next page
|
||||||
|
handlePagingChange((prev) => ({
|
||||||
|
...prev,
|
||||||
|
after: pagingResponse?.after,
|
||||||
|
total: pagingResponse?.total || prev.total,
|
||||||
|
}));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
showErrorToast(error as AxiosError);
|
showErrorToast(error as AxiosError);
|
||||||
} finally {
|
} finally {
|
||||||
@ -328,32 +306,6 @@ const GlossaryTermTab = ({ isGlossary, className }: GlossaryTermTabProps) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchExpadedTree = async () => {
|
|
||||||
setIsTableLoading(true);
|
|
||||||
setIsExpandingAll(true);
|
|
||||||
const key = isGlossary ? 'glossary' : 'parent';
|
|
||||||
const { data } = await getGlossaryTerms({
|
|
||||||
[key]: activeGlossary?.id || '',
|
|
||||||
limit: API_RES_MAX_SIZE,
|
|
||||||
fields: [
|
|
||||||
TabSpecificField.OWNERS,
|
|
||||||
TabSpecificField.PARENT,
|
|
||||||
TabSpecificField.CHILDREN,
|
|
||||||
],
|
|
||||||
});
|
|
||||||
setGlossaryChildTerms(buildTree(data) as ModifiedGlossary[]);
|
|
||||||
const keys = data.reduce((prev, curr) => {
|
|
||||||
if (curr.children?.length) {
|
|
||||||
prev.push(curr.fullyQualifiedName ?? '');
|
|
||||||
}
|
|
||||||
|
|
||||||
return prev;
|
|
||||||
}, [] as string[]);
|
|
||||||
|
|
||||||
setExpandedRowKeys(keys);
|
|
||||||
setIsTableLoading(false);
|
|
||||||
setIsExpandingAll(false);
|
|
||||||
};
|
|
||||||
const fetchAllTasks = useCallback(async () => {
|
const fetchAllTasks = useCallback(async () => {
|
||||||
if (!activeGlossary?.fullyQualifiedName) {
|
if (!activeGlossary?.fullyQualifiedName) {
|
||||||
return;
|
return;
|
||||||
@ -403,24 +355,14 @@ const GlossaryTermTab = ({ isGlossary, className }: GlossaryTermTabProps) => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const currentFQN = activeGlossary?.fullyQualifiedName;
|
const currentFQN = activeGlossary?.fullyQualifiedName;
|
||||||
|
|
||||||
if (
|
if (currentFQN && !isLoadingMore && currentFQN !== previousGlossaryFQN) {
|
||||||
currentFQN &&
|
|
||||||
!isLoadingMore &&
|
|
||||||
currentFQN !== previousGlossaryFQN &&
|
|
||||||
!toggleExpandBtn
|
|
||||||
) {
|
|
||||||
// Clear existing terms when switching glossaries
|
// Clear existing terms when switching glossaries
|
||||||
setGlossaryChildTerms([]);
|
setGlossaryChildTerms([]);
|
||||||
handlePagingChange((prev) => ({ ...prev, after: undefined }));
|
handlePagingChange((prev) => ({ ...prev, after: undefined }));
|
||||||
setPreviousGlossaryFQN(currentFQN);
|
setPreviousGlossaryFQN(currentFQN);
|
||||||
fetchAllTerms();
|
fetchAllTerms();
|
||||||
}
|
}
|
||||||
}, [
|
}, [activeGlossary?.fullyQualifiedName, isLoadingMore, previousGlossaryFQN]);
|
||||||
activeGlossary?.fullyQualifiedName,
|
|
||||||
isLoadingMore,
|
|
||||||
previousGlossaryFQN,
|
|
||||||
toggleExpandBtn,
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Clear terms when component unmounts
|
// Clear terms when component unmounts
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -458,45 +400,21 @@ const GlossaryTermTab = ({ isGlossary, className }: GlossaryTermTabProps) => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// For search mode, check searchPaging.hasMore; for regular mode, check paging.after
|
|
||||||
const canLoadMore = searchTerm
|
|
||||||
? searchPaging.hasMore
|
|
||||||
: paging.after !== undefined;
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
inView &&
|
inView &&
|
||||||
canLoadMore &&
|
paging.after !== undefined &&
|
||||||
!isLoadingMore &&
|
!isLoadingMore &&
|
||||||
!isTableLoading &&
|
!isTableLoading
|
||||||
!toggleExpandBtn
|
|
||||||
) {
|
) {
|
||||||
fetchAllTerms(true);
|
fetchAllTerms(true);
|
||||||
}
|
}
|
||||||
}, [
|
}, [inView, paging.after, isLoadingMore, isTableLoading]);
|
||||||
inView,
|
|
||||||
paging.after,
|
|
||||||
searchPaging.hasMore,
|
|
||||||
searchTerm,
|
|
||||||
isLoadingMore,
|
|
||||||
isTableLoading,
|
|
||||||
toggleExpandBtn,
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Monitor for DOM changes to detect when the table becomes scrollable
|
// Monitor for DOM changes to detect when the table becomes scrollable
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const observer = new MutationObserver(() => {
|
const observer = new MutationObserver(() => {
|
||||||
const scrollContainer = findScrollContainer();
|
const scrollContainer = findScrollContainer();
|
||||||
// Check if we can load more based on search vs regular mode
|
if (scrollContainer && paging.after !== undefined && !isLoadingMore) {
|
||||||
const canLoadMore = searchTerm
|
|
||||||
? searchPaging.hasMore
|
|
||||||
: paging.after !== undefined;
|
|
||||||
|
|
||||||
if (
|
|
||||||
scrollContainer &&
|
|
||||||
canLoadMore &&
|
|
||||||
!isLoadingMore &&
|
|
||||||
!toggleExpandBtn
|
|
||||||
) {
|
|
||||||
const { scrollHeight, clientHeight } = scrollContainer;
|
const { scrollHeight, clientHeight } = scrollContainer;
|
||||||
// If content doesn't fill the viewport, load more
|
// If content doesn't fill the viewport, load more
|
||||||
if (scrollHeight <= clientHeight + 10) {
|
if (scrollHeight <= clientHeight + 10) {
|
||||||
@ -517,30 +435,17 @@ const GlossaryTermTab = ({ isGlossary, className }: GlossaryTermTabProps) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return () => observer.disconnect();
|
return () => observer.disconnect();
|
||||||
}, [
|
}, [paging.after, isLoadingMore, findScrollContainer]);
|
||||||
paging.after,
|
|
||||||
searchPaging.hasMore,
|
|
||||||
searchTerm,
|
|
||||||
isLoadingMore,
|
|
||||||
findScrollContainer,
|
|
||||||
toggleExpandBtn,
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Additional scroll handler for parent container
|
// Additional scroll handler for parent container
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleScroll = (event: Event) => {
|
const handleScroll = (event: Event) => {
|
||||||
const scrollContainer = event.target as HTMLElement;
|
const scrollContainer = event.target as HTMLElement;
|
||||||
// Check if we can load more based on search vs regular mode
|
|
||||||
const canLoadMore = searchTerm
|
|
||||||
? searchPaging.hasMore
|
|
||||||
: paging.after !== undefined;
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
scrollContainer &&
|
scrollContainer &&
|
||||||
canLoadMore &&
|
paging.after !== undefined &&
|
||||||
!isLoadingMore &&
|
!isLoadingMore &&
|
||||||
!isTableLoading &&
|
!isTableLoading
|
||||||
!toggleExpandBtn
|
|
||||||
) {
|
) {
|
||||||
const { scrollTop, scrollHeight, clientHeight } = scrollContainer;
|
const { scrollTop, scrollHeight, clientHeight } = scrollContainer;
|
||||||
// Load more when user is 200px from the bottom
|
// Load more when user is 200px from the bottom
|
||||||
@ -566,8 +471,6 @@ const GlossaryTermTab = ({ isGlossary, className }: GlossaryTermTabProps) => {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}, [
|
}, [
|
||||||
paging.after,
|
paging.after,
|
||||||
searchPaging.hasMore,
|
|
||||||
searchTerm,
|
|
||||||
isLoadingMore,
|
isLoadingMore,
|
||||||
isTableLoading,
|
isTableLoading,
|
||||||
findScrollContainer,
|
findScrollContainer,
|
||||||
@ -923,13 +826,157 @@ const GlossaryTermTab = ({ isGlossary, className }: GlossaryTermTabProps) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const toggleExpandAll = useCallback(async () => {
|
const toggleExpandAll = useCallback(async () => {
|
||||||
setToggleExpandBtn((prev) => !prev);
|
if (isExpandingAll) {
|
||||||
|
return; // Prevent multiple simultaneous expand operations
|
||||||
|
}
|
||||||
|
|
||||||
if (expandedRowKeys.length === expandableKeys.length) {
|
if (expandedRowKeys.length === expandableKeys.length) {
|
||||||
// Collapse all - immediate UI update
|
// Collapse all - immediate UI update
|
||||||
setExpandedRowKeys([]);
|
setExpandedRowKeys([]);
|
||||||
fetchAllTerms();
|
|
||||||
} else {
|
} else {
|
||||||
fetchExpadedTree();
|
setIsExpandingAll(true);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Recursive function to load all children at all levels
|
||||||
|
const loadAllChildrenRecursively = async (
|
||||||
|
terms: ModifiedGlossary[],
|
||||||
|
depth = 0,
|
||||||
|
maxDepth = 10
|
||||||
|
): Promise<ModifiedGlossary[]> => {
|
||||||
|
if (depth >= maxDepth) {
|
||||||
|
return terms; // Prevent infinite recursion
|
||||||
|
}
|
||||||
|
|
||||||
|
const BATCH_SIZE = 5;
|
||||||
|
const termsToLoad = terms.filter(
|
||||||
|
(term) =>
|
||||||
|
term.childrenCount &&
|
||||||
|
term.childrenCount > 0 &&
|
||||||
|
(!term.children || term.children.length === 0)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (termsToLoad.length === 0) {
|
||||||
|
// If no terms need loading at this level, check children
|
||||||
|
const updatedTerms = await Promise.all(
|
||||||
|
terms.map(async (term) => {
|
||||||
|
if (term.children && term.children.length > 0) {
|
||||||
|
const updatedChildren = await loadAllChildrenRecursively(
|
||||||
|
term.children as ModifiedGlossary[],
|
||||||
|
depth + 1,
|
||||||
|
maxDepth
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
...term,
|
||||||
|
children: updatedChildren as ModifiedGlossaryTerm[],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return term;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
return updatedTerms;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load data for terms at this level
|
||||||
|
const batches: typeof termsToLoad[] = [];
|
||||||
|
for (let i = 0; i < termsToLoad.length; i += BATCH_SIZE) {
|
||||||
|
batches.push(termsToLoad.slice(i, i + BATCH_SIZE));
|
||||||
|
}
|
||||||
|
|
||||||
|
const childDataMap: Record<string, GlossaryTermWithChildren[]> = {};
|
||||||
|
|
||||||
|
for (const batch of batches) {
|
||||||
|
await Promise.all(
|
||||||
|
batch.map(async (term) => {
|
||||||
|
if (term.fullyQualifiedName) {
|
||||||
|
setLoadingChildren((prev) => ({
|
||||||
|
...prev,
|
||||||
|
[term.fullyQualifiedName as string]: true,
|
||||||
|
}));
|
||||||
|
try {
|
||||||
|
const { data } = await getGlossaryTermChildrenLazy(
|
||||||
|
term.fullyQualifiedName,
|
||||||
|
1000 // Get all children at once
|
||||||
|
);
|
||||||
|
childDataMap[term.fullyQualifiedName] = data;
|
||||||
|
} catch (error) {
|
||||||
|
showErrorToast(error as AxiosError);
|
||||||
|
} finally {
|
||||||
|
setLoadingChildren((prev) => ({
|
||||||
|
...prev,
|
||||||
|
[term.fullyQualifiedName as string]: false,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
// Small delay between batches to keep UI responsive
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 50));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update terms with loaded children
|
||||||
|
const termsWithChildren = terms.map((term) => {
|
||||||
|
const termFQN = term.fullyQualifiedName;
|
||||||
|
if (termFQN && childDataMap[termFQN]) {
|
||||||
|
return {
|
||||||
|
...term,
|
||||||
|
children: childDataMap[termFQN] as ModifiedGlossaryTerm[],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return term;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Recursively load children for the newly loaded terms
|
||||||
|
const fullyLoadedTerms = await Promise.all(
|
||||||
|
termsWithChildren.map(async (term) => {
|
||||||
|
if (term.children && term.children.length > 0) {
|
||||||
|
const updatedChildren = await loadAllChildrenRecursively(
|
||||||
|
term.children as ModifiedGlossary[],
|
||||||
|
depth + 1,
|
||||||
|
maxDepth
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
...term,
|
||||||
|
children: updatedChildren as ModifiedGlossaryTerm[],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return term;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
return fullyLoadedTerms;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Load all children recursively starting from current terms
|
||||||
|
const currentTerms = glossaryChildTerms;
|
||||||
|
if (!Array.isArray(currentTerms)) {
|
||||||
|
setIsExpandingAll(false);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fullyExpandedTerms = await loadAllChildrenRecursively(
|
||||||
|
currentTerms
|
||||||
|
);
|
||||||
|
|
||||||
|
// Update the glossary child terms with fully expanded tree
|
||||||
|
setGlossaryChildTerms(fullyExpandedTerms);
|
||||||
|
|
||||||
|
// Get all expandable keys from the fully loaded tree
|
||||||
|
const allExpandableKeys = getAllExpandableKeys(fullyExpandedTerms);
|
||||||
|
|
||||||
|
// Set all keys as expanded
|
||||||
|
setExpandedRowKeys(allExpandableKeys);
|
||||||
|
} catch (error) {
|
||||||
|
showErrorToast(error as AxiosError);
|
||||||
|
} finally {
|
||||||
|
setIsExpandingAll(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, [
|
}, [
|
||||||
glossaryTerms,
|
glossaryTerms,
|
||||||
@ -939,8 +986,10 @@ const GlossaryTermTab = ({ isGlossary, className }: GlossaryTermTabProps) => {
|
|||||||
setLoadingChildren,
|
setLoadingChildren,
|
||||||
expandedRowKeys,
|
expandedRowKeys,
|
||||||
expandableKeys,
|
expandableKeys,
|
||||||
|
setIsExpandingAll,
|
||||||
setExpandedRowKeys,
|
setExpandedRowKeys,
|
||||||
showErrorToast,
|
showErrorToast,
|
||||||
|
isExpandingAll,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const isAllExpanded = useMemo(() => {
|
const isAllExpanded = useMemo(() => {
|
||||||
@ -1062,6 +1111,7 @@ const GlossaryTermTab = ({ isGlossary, className }: GlossaryTermTabProps) => {
|
|||||||
<Button
|
<Button
|
||||||
className="text-primary remove-button-background-hover"
|
className="text-primary remove-button-background-hover"
|
||||||
data-testid="expand-collapse-all-button"
|
data-testid="expand-collapse-all-button"
|
||||||
|
disabled={isExpandingAll}
|
||||||
size="small"
|
size="small"
|
||||||
type="text"
|
type="text"
|
||||||
onClick={toggleExpandAll}>
|
onClick={toggleExpandAll}>
|
||||||
@ -1266,10 +1316,6 @@ const GlossaryTermTab = ({ isGlossary, className }: GlossaryTermTabProps) => {
|
|||||||
// Trigger new fetch when search term changes
|
// Trigger new fetch when search term changes
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (activeGlossary) {
|
if (activeGlossary) {
|
||||||
// Reset search pagination when search term changes
|
|
||||||
if (searchTerm) {
|
|
||||||
setSearchPaging({ offset: 0, total: undefined, hasMore: true });
|
|
||||||
}
|
|
||||||
fetchAllTerms();
|
fetchAllTerms();
|
||||||
}
|
}
|
||||||
}, [searchTerm, activeGlossary]);
|
}, [searchTerm, activeGlossary]);
|
||||||
@ -1336,9 +1382,7 @@ const GlossaryTermTab = ({ isGlossary, className }: GlossaryTermTabProps) => {
|
|||||||
onHeaderRow={onTableHeader}
|
onHeaderRow={onTableHeader}
|
||||||
onRow={onTableRow}
|
onRow={onTableRow}
|
||||||
/>
|
/>
|
||||||
{/* Show infinite scroll trigger if there are more results */}
|
{paging.after !== undefined && (
|
||||||
{((!searchTerm && paging.after !== undefined) ||
|
|
||||||
(searchTerm && searchPaging.hasMore)) && (
|
|
||||||
<div
|
<div
|
||||||
className="m-t-md m-b-md text-center p-y-lg"
|
className="m-t-md m-b-md text-center p-y-lg"
|
||||||
ref={infiniteScrollRef}
|
ref={infiniteScrollRef}
|
||||||
|
|||||||
@ -356,6 +356,26 @@ export type GlossaryTermWithChildren = Omit<GlossaryTerm, 'children'> & {
|
|||||||
children?: GlossaryTerm[];
|
children?: GlossaryTerm[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getFirstLevelGlossaryTerms = async (parentFQN: string) => {
|
||||||
|
const apiUrl = `/glossaryTerms`;
|
||||||
|
|
||||||
|
const { data } = await APIClient.get<
|
||||||
|
PagingResponse<GlossaryTermWithChildren[]>
|
||||||
|
>(apiUrl, {
|
||||||
|
params: {
|
||||||
|
directChildrenOf: parentFQN,
|
||||||
|
fields: [
|
||||||
|
TabSpecificField.CHILDREN_COUNT,
|
||||||
|
TabSpecificField.OWNERS,
|
||||||
|
TabSpecificField.REVIEWERS,
|
||||||
|
],
|
||||||
|
limit: 100000,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
export const getFirstLevelGlossaryTermsPaginated = async (
|
export const getFirstLevelGlossaryTermsPaginated = async (
|
||||||
parentFQN: string,
|
parentFQN: string,
|
||||||
pageSize = 50,
|
pageSize = 50,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user