diff --git a/openmetadata-ui/src/main/resources/ui/playwright/utils/task.ts b/openmetadata-ui/src/main/resources/ui/playwright/utils/task.ts index 2d71b8f66cc..07129203dde 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/utils/task.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/utils/task.ts @@ -156,7 +156,9 @@ export const checkTaskCount = async ( openTask = 0, closedTask = 0 ) => { - await page.waitForLoadState('networkidle'); + await page.waitForSelector('.ant-skeleton-element ', { + state: 'detached', + }); const openTaskElement = await page.getByTestId('open-task').textContent(); diff --git a/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/ActivityFeedTab/ActivityFeedTab.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/ActivityFeedTab/ActivityFeedTab.component.tsx index 8e7016e67bc..3bd9325efae 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/ActivityFeedTab/ActivityFeedTab.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/ActivityFeedTab/ActivityFeedTab.component.tsx @@ -10,12 +10,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Menu, Space, Typography } from 'antd'; +import { Menu, Skeleton, Space, Typography } from 'antd'; import { AxiosError } from 'axios'; import classNames from 'classnames'; import { noop } from 'lodash'; import { default as React, + ReactNode, RefObject, useCallback, useEffect, @@ -108,7 +109,13 @@ export const ActivityFeedTab = ({ const [taskFilter, setTaskFilter] = useState( ThreadTaskStatus.Open ); - const [count, setCount] = useState(FEED_COUNT_INITIAL_DATA); + const [countData, setCountData] = useState<{ + loading: boolean; + data: FeedCounts; + }>({ + loading: false, + data: FEED_COUNT_INITIAL_DATA, + }); const { postFeed, @@ -139,6 +146,17 @@ export const ActivityFeedTab = ({ [activeTab] ); + const getElementWithCountLoader = useCallback( + (element: ReactNode) => { + if (countData.loading) { + return ; + } + + return element; + }, + [countData.loading] + ); + const handleTabChange = (subTab: string) => { history.push( entityUtilClassBase.getEntityLink( @@ -169,29 +187,37 @@ export const ActivityFeedTab = ({ } }, [activeTab]); - const handleFeedCount = useCallback((data: FeedCounts) => { - setCount(data); - onUpdateFeedCount?.(data); - }, []); + const handleFeedCount = useCallback( + (data: FeedCounts) => { + setCountData((prev) => ({ ...prev, data })); + onUpdateFeedCount?.(data); + }, + [setCountData] + ); const fetchFeedsCount = async () => { + setCountData((prev) => ({ ...prev, loading: true })); if (isUserEntity) { try { const res = await getFeedCount(getEntityUserLink(fqn)); - setCount({ - conversationCount: res[0].conversationCount ?? 0, - totalTasksCount: res[0].totalTaskCount, - openTaskCount: res[0].openTaskCount ?? 0, - closedTaskCount: res[0].closedTaskCount ?? 0, - totalCount: res[0].conversationCount ?? 0 + res[0].totalTaskCount, - mentionCount: res[0].mentionCount ?? 0, - }); + setCountData((prev) => ({ + ...prev, + data: { + conversationCount: res[0].conversationCount ?? 0, + totalTasksCount: res[0].totalTaskCount, + openTaskCount: res[0].openTaskCount ?? 0, + closedTaskCount: res[0].closedTaskCount ?? 0, + totalCount: res[0].conversationCount ?? 0 + res[0].totalTaskCount, + mentionCount: res[0].mentionCount ?? 0, + }, + })); } catch (err) { showErrorToast(err as AxiosError, t('server.entity-feed-fetch-error')); } } else { - getFeedCounts(entityType, fqn, handleFeedCount); + await getFeedCounts(entityType, fqn, handleFeedCount); } + setCountData((prev) => ({ ...prev, loading: false })); }; const getThreadType = useCallback((activeTab) => { @@ -239,7 +265,7 @@ export const ActivityFeedTab = ({ const refetchFeedData = useCallback(() => { if ( - entityFeedTotalCount !== count.totalCount && + entityFeedTotalCount !== countData.data.totalCount && isActivityFeedTab && refetchFeed ) { @@ -259,7 +285,7 @@ export const ActivityFeedTab = ({ threadType, entityType, refetchFeed, - count.totalCount, + countData.data.totalCount, entityFeedTotalCount, isActivityFeedTab, ]); @@ -338,7 +364,7 @@ export const ActivityFeedTab = ({ {!isUserEntity && getCountBadge( - count.conversationCount, + countData.data.conversationCount, '', activeTab === ActivityFeedTabs.ALL )} @@ -362,7 +388,7 @@ export const ActivityFeedTab = ({ {getCountBadge( - count.mentionCount, + countData.data.mentionCount, '', activeTab === ActivityFeedTabs.MENTIONS )} @@ -384,7 +410,11 @@ export const ActivityFeedTab = ({ {t('label.task-plural')} - {getCountBadge(count.openTaskCount, '', isTaskActiveTab)} + {getCountBadge( + countData.data.openTaskCount, + '', + isTaskActiveTab + )} ), @@ -400,33 +430,37 @@ export const ActivityFeedTab = ({
{isTaskActiveTab && (
- { - handleUpdateTaskFilter(ThreadTaskStatus.Open); - setActiveThread(); - }}> - {count.openTaskCount}{' '} - {t('label.open')} - - { - handleUpdateTaskFilter(ThreadTaskStatus.Closed); - setActiveThread(); - }}> - {' '} - {count.closedTaskCount} {t('label.closed')} - + {getElementWithCountLoader( + { + handleUpdateTaskFilter(ThreadTaskStatus.Open); + setActiveThread(); + }}> + {' '} + {countData.data.openTaskCount} {t('label.open')} + + )} + {getElementWithCountLoader( + { + handleUpdateTaskFilter(ThreadTaskStatus.Closed); + setActiveThread(); + }}> + {' '} + {countData.data.closedTaskCount} {t('label.closed')} + + )}
)} { * @param onDataFetched - callback function which return FeedCounts object */ -export const getFeedCounts = ( +export const getFeedCounts = async ( entityType: string, entityFQN: string, feedCountCallback: (countValue: FeedCounts) => void ) => { - getFeedCount(getEntityFeedLink(entityType, entityFQN)) - .then((res) => { - if (res) { - const { - conversationCount, - openTaskCount, - closedTaskCount, - totalTasksCount, - totalCount, - mentionCount, - } = res.reduce((acc, item) => { - const conversationCount = - acc.conversationCount + (item.conversationCount || 0); - const totalTasksCount = - acc.totalTasksCount + (item.totalTaskCount || 0); + try { + const res = await getFeedCount(getEntityFeedLink(entityType, entityFQN)); + if (res) { + const { + conversationCount, + openTaskCount, + closedTaskCount, + totalTasksCount, + totalCount, + mentionCount, + } = res.reduce((acc, item) => { + const conversationCount = + acc.conversationCount + (item.conversationCount || 0); + const totalTasksCount = + acc.totalTasksCount + (item.totalTaskCount || 0); - return { - conversationCount, - totalTasksCount, - openTaskCount: acc.openTaskCount + (item.openTaskCount || 0), - closedTaskCount: acc.closedTaskCount + (item.closedTaskCount || 0), - totalCount: conversationCount + totalTasksCount, - mentionCount: acc.mentionCount + (item.mentionCount || 0), - }; - }, FEED_COUNT_INITIAL_DATA); - - feedCountCallback({ + return { conversationCount, totalTasksCount, - openTaskCount, - closedTaskCount, - totalCount, - mentionCount, - }); - } else { - throw t('server.entity-feed-fetch-error'); - } - }) - .catch((err: AxiosError) => { - showErrorToast(err, t('server.entity-feed-fetch-error')); - }); + openTaskCount: acc.openTaskCount + (item.openTaskCount || 0), + closedTaskCount: acc.closedTaskCount + (item.closedTaskCount || 0), + totalCount: conversationCount + totalTasksCount, + mentionCount: acc.mentionCount + (item.mentionCount || 0), + }; + }, FEED_COUNT_INITIAL_DATA); + + feedCountCallback({ + conversationCount, + totalTasksCount, + openTaskCount, + closedTaskCount, + totalCount, + mentionCount, + }); + } else { + throw t('server.entity-feed-fetch-error'); + } + } catch (err) { + showErrorToast(err as AxiosError, t('server.entity-feed-fetch-error')); + } }; /**