fix(ui): infinite scroll issue in user activity feed page (#12617)

* fix the infinite scroll issue in user activity feed page

* fix the functionality issue in activity thread on entity page

* minor code fixes
This commit is contained in:
Ashish Gupta 2023-07-28 14:52:36 +05:30 committed by GitHub
parent 515c68d488
commit fde17d44b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 121 additions and 144 deletions

View File

@ -68,7 +68,7 @@ const ActivityFeedListV1 = ({
}
return (
<div className="feed-list-container p-y-md m-b-sm h-full" id="feedData">
<div className="feed-list-container p-y-md" id="feedData">
{entityThread.length === 0 && (
<div
className="h-full p-x-md"

View File

@ -126,10 +126,6 @@ const ActivityFeedProvider = ({ children, user }: Props) => {
);
setEntityThread((prev) => (after ? [...prev, ...data] : [...data]));
setEntityPaging(paging);
setLoading(false);
return data;
} catch (err) {
showErrorToast(
err as AxiosError,
@ -137,8 +133,6 @@ const ActivityFeedProvider = ({ children, user }: Props) => {
entity: t('label.activity-feed'),
})
);
return [];
} finally {
setLoading(false);
}

View File

@ -51,7 +51,7 @@ export interface ActivityFeedProviderContextType {
type?: ThreadType,
entityType?: EntityType,
fqn?: string
) => Promise<Thread[]>;
) => Promise<void>;
showDrawer: (thread: Thread) => void;
hideDrawer: () => void;
updateEditorFocus: (isFocused: boolean) => void;

View File

@ -14,6 +14,7 @@ import { Menu, Space, Typography } from 'antd';
import classNames from 'classnames';
import Loader from 'components/Loader/Loader';
import { TaskTab } from 'components/Task/TaskTab/TaskTab.component';
import { ICON_DIMENSION } from 'constants/constants';
import { observerOptions } from 'constants/Mydata.constants';
import { EntityTabs, EntityType } from 'enums/entity.enum';
import { FeedFilter } from 'enums/mydata.enum';
@ -22,7 +23,6 @@ import {
ThreadTaskStatus,
ThreadType,
} from 'generated/entity/feed/thread';
import { Paging } from 'generated/type/paging';
import { useElementInView } from 'hooks/useElementInView';
import { noop } from 'lodash';
import {
@ -50,12 +50,10 @@ import {
ActivityFeedTabs,
TaskFilter,
} from './ActivityFeedTab.interface';
import { ReactComponent as CheckIcon } from '/assets/svg/ic-check.svg';
import { ReactComponent as TaskIcon } from '/assets/svg/ic-task.svg';
import { ICON_DIMENSION } from 'constants/constants';
import { ReactComponent as AllActivityIcon } from '/assets/svg/all-activity-v2.svg';
import { ReactComponent as CheckIcon } from '/assets/svg/ic-check.svg';
import { ReactComponent as MentionIcon } from '/assets/svg/ic-mentions.svg';
import { ReactComponent as TaskIcon } from '/assets/svg/ic-task.svg';
import { ReactComponent as TaskListIcon } from '/assets/svg/task-ic.svg';
export const ActivityFeedTab = ({
@ -67,7 +65,11 @@ export const ActivityFeedTab = ({
}: ActivityFeedTabProps) => {
const history = useHistory();
const { t } = useTranslation();
const [elementRef, isInView] = useElementInView(observerOptions);
const [elementRef, isInView] = useElementInView({
...observerOptions,
root: document.querySelector('#center-container'),
rootMargin: '0px 0px 2px 0px',
});
const { subTab: activeTab = ActivityFeedTabs.ALL } =
useParams<{ subTab: ActivityFeedTabs }>();
const [taskFilter, setTaskFilter] = useState<TaskFilter>('open');
@ -204,7 +206,7 @@ export const ActivityFeedTab = ({
(after?: string) => {
getFeedData(feedFilter, after, threadType, entityType, fqn);
},
[threadType, feedFilter, entityType, fqn]
[threadType, feedFilter, entityType, fqn, getFeedData]
);
useEffect(() => {
@ -220,19 +222,9 @@ export const ActivityFeedTab = ({
[setActiveThread]
);
const fetchMoreThread = (
isElementInView: boolean,
pagingObj: Paging,
isLoading: boolean
) => {
if (isElementInView && pagingObj?.after && !isLoading) {
handleFeedFetchFromFeedList(pagingObj.after);
}
};
useEffect(() => {
if (fqn) {
fetchMoreThread(isInView, entityPaging, loading);
if (fqn && isInView && entityPaging.after && !loading) {
handleFeedFetchFromFeedList(entityPaging.after);
}
}, [entityPaging, loading, isInView, fqn]);
@ -340,7 +332,7 @@ export const ActivityFeedTab = ({
onClick={(info) => handleTabChange(info.key)}
/>
<div className=" center-container">
<div className="center-container" id="center-container">
{isTaskActiveTab && (
<div className="d-flex gap-4 p-sm p-x-lg activity-feed-task">
<Typography.Text

View File

@ -14,9 +14,7 @@
import { Col, Row, Space, Table, Tabs, Typography } from 'antd';
import { ColumnsType } from 'antd/lib/table';
import { AxiosError } from 'axios';
import ActivityFeedProvider, {
useActivityFeedProvider,
} from 'components/ActivityFeed/ActivityFeedProvider/ActivityFeedProvider';
import { useActivityFeedProvider } from 'components/ActivityFeed/ActivityFeedProvider/ActivityFeedProvider';
import { ActivityFeedTab } from 'components/ActivityFeed/ActivityFeedTab/ActivityFeedTab.component';
import DescriptionV1 from 'components/common/description/DescriptionV1';
import ErrorPlaceHolder from 'components/common/error-with-placeholder/ErrorPlaceHolder';
@ -66,6 +64,7 @@ import {
DashboardDetailsProps,
} from './DashboardDetails.interface';
import { withActivityFeed } from 'components/router/withActivityFeed';
import TableDescription from 'components/TableDescription/TableDescription.component';
import { DisplayType } from 'components/Tag/TagsViewer/TagsViewer.interface';
@ -650,14 +649,12 @@ const DashboardDetails = ({
),
key: EntityTabs.ACTIVITY_FEED,
children: (
<ActivityFeedProvider>
<ActivityFeedTab
entityType={EntityType.DASHBOARD}
fqn={dashboardDetails?.fullyQualifiedName ?? ''}
onFeedUpdate={getEntityFeedCount}
onUpdateEntityDetails={fetchDashboard}
/>
</ActivityFeedProvider>
<ActivityFeedTab
entityType={EntityType.DASHBOARD}
fqn={dashboardDetails?.fullyQualifiedName ?? ''}
onFeedUpdate={getEntityFeedCount}
onUpdateEntityDetails={fetchDashboard}
/>
),
},
{
@ -778,4 +775,4 @@ const DashboardDetails = ({
);
};
export default DashboardDetails;
export default withActivityFeed<DashboardDetailsProps>(DashboardDetails);

View File

@ -12,9 +12,7 @@
*/
import { Card, Col, Row, Space, Tabs } from 'antd';
import ActivityFeedProvider, {
useActivityFeedProvider,
} from 'components/ActivityFeed/ActivityFeedProvider/ActivityFeedProvider';
import { useActivityFeedProvider } from 'components/ActivityFeed/ActivityFeedProvider/ActivityFeedProvider';
import { ActivityFeedTab } from 'components/ActivityFeed/ActivityFeedTab/ActivityFeedTab.component';
import ActivityThreadPanel from 'components/ActivityFeed/ActivityThreadPanel/ActivityThreadPanel';
import DescriptionV1 from 'components/common/description/DescriptionV1';
@ -22,6 +20,7 @@ import PageLayoutV1 from 'components/containers/PageLayoutV1';
import { DataAssetsHeader } from 'components/DataAssets/DataAssetsHeader/DataAssetsHeader.component';
import EntityLineageComponent from 'components/EntityLineage/EntityLineage.component';
import { EntityName } from 'components/Modals/EntityNameModal/EntityNameModal.interface';
import { withActivityFeed } from 'components/router/withActivityFeed';
import SchemaEditor from 'components/schema-editor/SchemaEditor';
import { SourceType } from 'components/searched-data/SearchedData.interface';
import TabsLabel from 'components/TabsLabel/TabsLabel.component';
@ -270,14 +269,12 @@ const DataModelDetails = ({
),
key: EntityTabs.ACTIVITY_FEED,
children: (
<ActivityFeedProvider>
<ActivityFeedTab
entityType={EntityType.DASHBOARD_DATA_MODEL}
fqn={dataModelData?.fullyQualifiedName ?? ''}
onFeedUpdate={getEntityFeedCount}
onUpdateEntityDetails={fetchDataModel}
/>
</ActivityFeedProvider>
<ActivityFeedTab
entityType={EntityType.DASHBOARD_DATA_MODEL}
fqn={dataModelData?.fullyQualifiedName ?? ''}
onFeedUpdate={getEntityFeedCount}
onUpdateEntityDetails={fetchDataModel}
/>
),
},
...(dataModelData?.sql
@ -377,4 +374,4 @@ const DataModelDetails = ({
);
};
export default DataModelDetails;
export default withActivityFeed<DataModelDetailsProps>(DataModelDetails);

View File

@ -14,15 +14,14 @@
import { Col, Row, Space, Table, Tabs, Typography } from 'antd';
import { ColumnsType } from 'antd/lib/table';
import { AxiosError } from 'axios';
import ActivityFeedProvider, {
useActivityFeedProvider,
} from 'components/ActivityFeed/ActivityFeedProvider/ActivityFeedProvider';
import { useActivityFeedProvider } from 'components/ActivityFeed/ActivityFeedProvider/ActivityFeedProvider';
import { ActivityFeedTab } from 'components/ActivityFeed/ActivityFeedTab/ActivityFeedTab.component';
import DescriptionV1 from 'components/common/description/DescriptionV1';
import ErrorPlaceHolder from 'components/common/error-with-placeholder/ErrorPlaceHolder';
import PageLayoutV1 from 'components/containers/PageLayoutV1';
import { DataAssetsHeader } from 'components/DataAssets/DataAssetsHeader/DataAssetsHeader.component';
import { EntityName } from 'components/Modals/EntityNameModal/EntityNameModal.interface';
import { withActivityFeed } from 'components/router/withActivityFeed';
import TabsLabel from 'components/TabsLabel/TabsLabel.component';
import TagsContainerV2 from 'components/Tag/TagsContainerV2/TagsContainerV2';
import { DisplayType } from 'components/Tag/TagsViewer/TagsViewer.interface';
@ -472,14 +471,12 @@ const MlModelDetail: FC<MlModelDetailProp> = ({
),
key: EntityTabs.ACTIVITY_FEED,
children: (
<ActivityFeedProvider>
<ActivityFeedTab
entityType={EntityType.MLMODEL}
fqn={mlModelDetail?.fullyQualifiedName ?? ''}
onFeedUpdate={fetchEntityFeedCount}
onUpdateEntityDetails={fetchMlModel}
/>
</ActivityFeedProvider>
<ActivityFeedTab
entityType={EntityType.MLMODEL}
fqn={mlModelDetail?.fullyQualifiedName ?? ''}
onFeedUpdate={fetchEntityFeedCount}
onUpdateEntityDetails={fetchMlModel}
/>
),
},
{
@ -596,4 +593,4 @@ const MlModelDetail: FC<MlModelDetailProp> = ({
);
};
export default MlModelDetail;
export default withActivityFeed<MlModelDetailProp>(MlModelDetail);

View File

@ -14,9 +14,7 @@
import { Card, Col, Radio, Row, Space, Tabs, Typography } from 'antd';
import Table, { ColumnsType } from 'antd/lib/table';
import { AxiosError } from 'axios';
import ActivityFeedProvider, {
useActivityFeedProvider,
} from 'components/ActivityFeed/ActivityFeedProvider/ActivityFeedProvider';
import { useActivityFeedProvider } from 'components/ActivityFeed/ActivityFeedProvider/ActivityFeedProvider';
import { ActivityFeedTab } from 'components/ActivityFeed/ActivityFeedTab/ActivityFeedTab.component';
import { CustomPropertyTable } from 'components/common/CustomPropertyTable/CustomPropertyTable';
import { CustomPropertyProps } from 'components/common/CustomPropertyTable/CustomPropertyTable.interface';
@ -27,6 +25,7 @@ import { DataAssetsHeader } from 'components/DataAssets/DataAssetsHeader/DataAss
import EntityLineageComponent from 'components/EntityLineage/EntityLineage.component';
import ExecutionsTab from 'components/Execution/Execution.component';
import { EntityName } from 'components/Modals/EntityNameModal/EntityNameModal.interface';
import { withActivityFeed } from 'components/router/withActivityFeed';
import TableDescription from 'components/TableDescription/TableDescription.component';
import TableTags from 'components/TableTags/TableTags.component';
import TabsLabel from 'components/TabsLabel/TabsLabel.component';
@ -648,14 +647,12 @@ const PipelineDetails = ({
),
key: EntityTabs.ACTIVITY_FEED,
children: (
<ActivityFeedProvider>
<ActivityFeedTab
entityType={EntityType.PIPELINE}
fqn={pipelineDetails?.fullyQualifiedName ?? ''}
onFeedUpdate={getEntityFeedCount}
onUpdateEntityDetails={fetchPipeline}
/>
</ActivityFeedProvider>
<ActivityFeedTab
entityType={EntityType.PIPELINE}
fqn={pipelineDetails?.fullyQualifiedName ?? ''}
onFeedUpdate={getEntityFeedCount}
onUpdateEntityDetails={fetchPipeline}
/>
),
},
{
@ -803,4 +800,4 @@ const PipelineDetails = ({
);
};
export default PipelineDetails;
export default withActivityFeed<PipeLineDetailsProp>(PipelineDetails);

View File

@ -13,9 +13,7 @@
import { Col, Row, Space, Tabs } from 'antd';
import { AxiosError } from 'axios';
import ActivityFeedProvider, {
useActivityFeedProvider,
} from 'components/ActivityFeed/ActivityFeedProvider/ActivityFeedProvider';
import { useActivityFeedProvider } from 'components/ActivityFeed/ActivityFeedProvider/ActivityFeedProvider';
import { ActivityFeedTab } from 'components/ActivityFeed/ActivityFeedTab/ActivityFeedTab.component';
import DescriptionV1 from 'components/common/description/DescriptionV1';
import ErrorPlaceHolder from 'components/common/error-with-placeholder/ErrorPlaceHolder';
@ -24,6 +22,7 @@ import PageLayoutV1 from 'components/containers/PageLayoutV1';
import { DataAssetsHeader } from 'components/DataAssets/DataAssetsHeader/DataAssetsHeader.component';
import EntityLineageComponent from 'components/EntityLineage/EntityLineage.component';
import { EntityName } from 'components/Modals/EntityNameModal/EntityNameModal.interface';
import { withActivityFeed } from 'components/router/withActivityFeed';
import SampleDataTopic from 'components/SampleDataTopic/SampleDataTopic';
import TabsLabel from 'components/TabsLabel/TabsLabel.component';
import TagsContainerV2 from 'components/Tag/TagsContainerV2/TagsContainerV2';
@ -360,14 +359,12 @@ const TopicDetails: React.FC<TopicDetailsProps> = ({
),
key: EntityTabs.ACTIVITY_FEED,
children: (
<ActivityFeedProvider>
<ActivityFeedTab
entityType={EntityType.TOPIC}
fqn={topicDetails?.fullyQualifiedName ?? ''}
onFeedUpdate={getEntityFeedCount}
onUpdateEntityDetails={fetchTopic}
/>
</ActivityFeedProvider>
<ActivityFeedTab
entityType={EntityType.TOPIC}
fqn={topicDetails?.fullyQualifiedName ?? ''}
onFeedUpdate={getEntityFeedCount}
onUpdateEntityDetails={fetchTopic}
/>
),
},
{
@ -492,4 +489,4 @@ const TopicDetails: React.FC<TopicDetailsProps> = ({
);
};
export default TopicDetails;
export default withActivityFeed<TopicDetailsProps>(TopicDetails);

View File

@ -102,6 +102,19 @@ const Users = ({
}
}, [tab, ownedEntities, followingEntities]);
const activityFeed = useMemo(
() => (
<ActivityFeedProvider user={userData.id}>
<ActivityFeedTab
entityType={EntityType.USER_NAME}
fqn={username}
onFeedUpdate={noop}
/>
</ActivityFeedProvider>
),
[userData, username]
);
const tabDetails = useMemo(() => {
switch (tab) {
case UserPageTabs.FOLLOWING:
@ -152,15 +165,7 @@ const Users = ({
);
}
case UserPageTabs.ACTIVITY:
return (
<ActivityFeedProvider user={userData.id}>
<ActivityFeedTab
entityType={EntityType.USER_NAME}
fqn={username}
onFeedUpdate={noop}
/>
</ActivityFeedProvider>
);
return activityFeed;
default:
return <></>;
@ -172,6 +177,7 @@ const Users = ({
isUserEntitiesLoading,
userPageFilterList,
entityDetails,
activityFeed,
]);
return (

View File

@ -41,29 +41,11 @@ const FeedsWidget = () => {
useEffect(() => {
if (activeTab === ActivityFeedTabs.ALL) {
getFeedData(FeedFilter.OWNER, undefined, ThreadType.Conversation).catch(
() => {
// ignore since error is displayed in toast in the parent promise.
// Added block for sonar code smell
}
);
getFeedData(FeedFilter.OWNER, undefined, ThreadType.Conversation);
} else if (activeTab === ActivityFeedTabs.MENTIONS) {
getFeedData(FeedFilter.MENTIONS).catch(() => {
// ignore since error is displayed in toast in the parent promise.
// Added block for sonar code smell
});
getFeedData(FeedFilter.MENTIONS);
} else if (activeTab === ActivityFeedTabs.TASKS) {
getFeedData(FeedFilter.OWNER, undefined, ThreadType.Task)
.then((data) => {
const openTasks = data.filter(
(item) => item.task?.status === ThreadTaskStatus.Open
);
setTaskCount(openTasks.length);
})
.catch(() => {
// ignore since error is displayed in toast in the parent promise.
// Added block for sonar code smell
});
getFeedData(FeedFilter.OWNER, undefined, ThreadType.Task);
}
}, [activeTab]);

View File

@ -0,0 +1,24 @@
/*
* Copyright 2023 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 ActivityFeedProvider from 'components/ActivityFeed/ActivityFeedProvider/ActivityFeedProvider';
import React, { FC } from 'react';
export const withActivityFeed =
<T extends unknown>(Component: FC<T>) =>
(props: JSX.IntrinsicAttributes & { children?: React.ReactNode } & T) => {
return (
<ActivityFeedProvider>
<Component {...props} />
</ActivityFeedProvider>
);
};

View File

@ -13,9 +13,7 @@
import { Col, Row, Space, Tabs } from 'antd';
import AppState from 'AppState';
import { AxiosError } from 'axios';
import ActivityFeedProvider, {
useActivityFeedProvider,
} from 'components/ActivityFeed/ActivityFeedProvider/ActivityFeedProvider';
import { useActivityFeedProvider } from 'components/ActivityFeed/ActivityFeedProvider/ActivityFeedProvider';
import { ActivityFeedTab } from 'components/ActivityFeed/ActivityFeedTab/ActivityFeedTab.component';
import ActivityThreadPanel from 'components/ActivityFeed/ActivityThreadPanel/ActivityThreadPanel';
import { CustomPropertyTable } from 'components/common/CustomPropertyTable/CustomPropertyTable';
@ -34,6 +32,7 @@ import {
OperationPermission,
ResourceEntity,
} from 'components/PermissionProvider/PermissionProvider.interface';
import { withActivityFeed } from 'components/router/withActivityFeed';
import TabsLabel from 'components/TabsLabel/TabsLabel.component';
import TagsContainerV2 from 'components/Tag/TagsContainerV2/TagsContainerV2';
import { DisplayType } from 'components/Tag/TagsViewer/TagsViewer.interface';
@ -560,14 +559,12 @@ const ContainerPage = () => {
),
key: EntityTabs.ACTIVITY_FEED,
children: (
<ActivityFeedProvider>
<ActivityFeedTab
entityType={EntityType.CONTAINER}
fqn={containerName}
onFeedUpdate={getEntityFeedCount}
onUpdateEntityDetails={() => fetchContainerDetail(containerName)}
/>
</ActivityFeedProvider>
<ActivityFeedTab
entityType={EntityType.CONTAINER}
fqn={containerName}
onFeedUpdate={getEntityFeedCount}
onUpdateEntityDetails={() => fetchContainerDetail(containerName)}
/>
),
},
{
@ -731,4 +728,4 @@ const ContainerPage = () => {
);
};
export default observer(ContainerPage);
export default withActivityFeed(observer(ContainerPage));

View File

@ -13,9 +13,7 @@
import { Col, Row, Space, Tabs, Typography } from 'antd';
import { AxiosError } from 'axios';
import classNames from 'classnames';
import ActivityFeedProvider, {
useActivityFeedProvider,
} from 'components/ActivityFeed/ActivityFeedProvider/ActivityFeedProvider';
import { useActivityFeedProvider } from 'components/ActivityFeed/ActivityFeedProvider/ActivityFeedProvider';
import { ActivityFeedTab } from 'components/ActivityFeed/ActivityFeedTab/ActivityFeedTab.component';
import ActivityThreadPanel from 'components/ActivityFeed/ActivityThreadPanel/ActivityThreadPanel';
import { CustomPropertyTable } from 'components/common/CustomPropertyTable/CustomPropertyTable';
@ -33,6 +31,7 @@ import {
OperationPermission,
ResourceEntity,
} from 'components/PermissionProvider/PermissionProvider.interface';
import { withActivityFeed } from 'components/router/withActivityFeed';
import SampleDataTableComponent from 'components/SampleDataTable/SampleDataTable.component';
import SchemaTab from 'components/SchemaTab/SchemaTab.component';
import { SourceType } from 'components/searched-data/SearchedData.interface';
@ -549,16 +548,14 @@ const TableDetailsPageV1 = () => {
),
key: EntityTabs.ACTIVITY_FEED,
children: (
<ActivityFeedProvider>
<ActivityFeedTab
columns={tableDetails?.columns}
entityType={EntityType.TABLE}
fqn={tableDetails?.fullyQualifiedName ?? ''}
owner={tableDetails?.owner}
onFeedUpdate={getEntityFeedCount}
onUpdateEntityDetails={fetchTableDetails}
/>
</ActivityFeedProvider>
<ActivityFeedTab
columns={tableDetails?.columns}
entityType={EntityType.TABLE}
fqn={tableDetails?.fullyQualifiedName ?? ''}
owner={tableDetails?.owner}
onFeedUpdate={getEntityFeedCount}
onUpdateEntityDetails={fetchTableDetails}
/>
),
},
{
@ -935,4 +932,4 @@ const TableDetailsPageV1 = () => {
);
};
export default TableDetailsPageV1;
export default withActivityFeed(TableDetailsPageV1);