fix(ui): user page scroll issue on tabs and pagination (#12424)

* fix user page scroll on tabs and pagination too

* changes as per comments

* fix unit test
This commit is contained in:
Ashish Gupta 2023-07-15 12:06:51 +05:30 committed by GitHub
parent fc29eba285
commit 00934279c6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 108 additions and 81 deletions

View File

@ -139,8 +139,7 @@ const mockProp = {
updateThreadHandler: jest.fn(),
setFeedFilter: jest.fn(),
threadType: 'Task' as ThreadType.Task,
onFollowingEntityPaginate: jest.fn(),
onOwnedEntityPaginate: jest.fn(),
handlePaginate: jest.fn(),
onSwitchChange: jest.fn(),
};

View File

@ -11,7 +11,17 @@
* limitations under the License.
*/
import { Card, Image, Input, Select, Space, Tabs, Typography } from 'antd';
import {
Card,
Col,
Image,
Input,
Row,
Select,
Space,
Tabs,
Typography,
} from 'antd';
import { ReactComponent as EditIcon } from 'assets/svg/edit-new.svg';
import { ReactComponent as IconTeamsGrey } from 'assets/svg/teams-grey.svg';
import { AxiosError } from 'axios';
@ -80,8 +90,7 @@ const Users = ({
isLoggedinUser,
isAuthDisabled,
username,
onFollowingEntityPaginate,
onOwnedEntityPaginate,
handlePaginate,
}: Props) => {
const { tab = UserPageTabs.ACTIVITY } = useParams<{ tab: UserPageTabs }>();
const [displayName, setDisplayName] = useState(userData.displayName);
@ -692,33 +701,17 @@ const Users = ({
}
return (
<PageLayoutV1
className="user-page-layout"
pageTitle={t('label.user')}
rightPanel={
showSummaryPanel &&
entityDetails && (
<EntitySummaryPanel
entityDetails={{ details: entityDetails }}
handleClosePanel={handleClosePanel}
/>
)
}
rightPanelWidth={400}>
<Row className="user-page-layout" wrap={false}>
<Col className="user-layout-scroll" flex="auto">
{entityData.data.length ? (
<SearchedData
currentPage={entityData.currPage}
data={entityData.data ?? []}
handleSummaryPanelDisplay={handleSummaryPanelDisplay}
isFilterSelected={false}
isSummaryPanelVisible={showSummaryPanel}
selectedEntityId={entityDetails?.id || ''}
totalValue={entityData.total ?? 0}
onPaginationChange={
tab === UserPageTabs.MY_DATA
? onOwnedEntityPaginate
: onFollowingEntityPaginate
}
onPaginationChange={handlePaginate}
/>
) : (
<ErrorPlaceHolder className="m-0">
@ -733,7 +726,17 @@ const Users = ({
</Typography.Paragraph>
</ErrorPlaceHolder>
)}
</PageLayoutV1>
</Col>
{showSummaryPanel && entityDetails && (
<Col className="user-page-layout-right-panel " flex="400px">
<EntitySummaryPanel
entityDetails={{ details: entityDetails }}
handleClosePanel={handleClosePanel}
/>
</Col>
)}
</Row>
);
}
case UserPageTabs.ACTIVITY:

View File

@ -19,21 +19,18 @@ export interface Props {
followingEntities: {
data: SearchedDataProps['data'];
total: number;
currPage: number;
};
ownedEntities: {
data: SearchedDataProps['data'];
total: number;
currPage: number;
};
username: string;
isUserEntitiesLoading: boolean;
isAdminUser: boolean;
isLoggedinUser: boolean;
isAuthDisabled: boolean;
handlePaginate: (page: string | number) => void;
updateUserDetails: (data: Partial<User>) => Promise<void>;
onFollowingEntityPaginate: (page: string | number) => void;
onOwnedEntityPaginate: (page: string | number) => void;
}
export enum UserPageTabs {

View File

@ -29,8 +29,12 @@
}
.user-page-layout {
.user-layout-scroll {
height: @users-page-tabs-height;
.page-layout-rightpanel {
overflow-y: scroll;
}
.user-page-layout-right-panel {
padding-right: 0 !important;
background-color: @white;
border: 1px solid @border-color;

View File

@ -91,5 +91,4 @@ export interface SearchedDataProps {
entityType: string
) => void;
filter?: Qs.ParsedQs;
currentPage?: number;
}

View File

@ -48,7 +48,6 @@ const SearchedData: React.FC<SearchedDataProps> = ({
selectedEntityId,
handleSummaryPanelDisplay,
filter,
currentPage,
}) => {
const searchResultCards = useMemo(() => {
return data.map(({ _source: table, highlight }, index) => {
@ -159,11 +158,7 @@ const SearchedData: React.FC<SearchedDataProps> = ({
<Pagination
hideOnSinglePage
className="text-center"
current={
isNumber(Number(page ?? currentPage))
? Number(page ?? currentPage)
: 1
}
current={isNumber(Number(page)) ? Number(page) : 1}
pageSize={
size && isNumber(Number(size))
? Number(size)

View File

@ -18,10 +18,16 @@ import Users from 'components/Users/Users.component';
import { compare } from 'fast-json-patch';
import { isEmpty } from 'lodash';
import { observer } from 'mobx-react';
import { AssetsDataType } from 'Models';
import React, { Dispatch, SetStateAction, useEffect, useState } from 'react';
import Qs from 'qs';
import React, {
Dispatch,
SetStateAction,
useEffect,
useMemo,
useState,
} from 'react';
import { useTranslation } from 'react-i18next';
import { useParams } from 'react-router-dom';
import { useHistory, useParams } from 'react-router-dom';
import { searchData } from 'rest/miscAPI';
import { getUserByName, updateUserDetail } from 'rest/userAPI';
import AppState from '../../AppState';
@ -32,8 +38,10 @@ import { User } from '../../generated/entity/teams/user';
import { useAuth } from '../../hooks/authHooks';
import { SearchEntityHits } from '../../utils/APIUtils';
import { showErrorToast } from '../../utils/ToastUtils';
import { UserAssetsDataType } from './UserPage.interface';
const UserPage = () => {
const history = useHistory();
const { t } = useTranslation();
const { username, tab = UserProfileTab.ACTIVITY } =
useParams<{ [key: string]: string }>();
@ -46,17 +54,26 @@ const UserPage = () => {
const [isUserEntitiesLoading, setIsUserEntitiesLoading] =
useState<boolean>(false);
const [followingEntities, setFollowingEntities] = useState<AssetsDataType>({
const [followingEntities, setFollowingEntities] =
useState<UserAssetsDataType>({
data: [],
total: 0,
currPage: 1,
});
const [ownedEntities, setOwnedEntities] = useState<AssetsDataType>({
const [ownedEntities, setOwnedEntities] = useState<UserAssetsDataType>({
data: [],
total: 0,
currPage: 1,
});
const { page = 1 } = useMemo(
() =>
Qs.parse(
location.search.startsWith('?')
? location.search.substr(1)
: location.search
),
[location.search]
);
const fetchUserData = () => {
setUserData({} as User);
getUserByName(username, 'profile,roles,teams')
@ -95,16 +112,14 @@ const UserPage = () => {
const fetchEntities = async (
fetchOwnedEntities = false,
handleEntity: Dispatch<SetStateAction<AssetsDataType>>
handleEntity: Dispatch<SetStateAction<UserAssetsDataType>>
) => {
const entity = fetchOwnedEntities ? ownedEntities : followingEntities;
if (userData.id) {
setIsUserEntitiesLoading(true);
try {
const response = await searchData(
'',
entity.currPage,
Number(page),
PAGE_SIZE,
getQueryFilters(fetchOwnedEntities),
'',
@ -118,14 +133,12 @@ const UserPage = () => {
handleEntity({
data: hits,
total,
currPage: entity.currPage,
});
} else {
const total = 0;
handleEntity({
data: [],
total,
currPage: entity.currPage,
});
}
} catch (error) {
@ -141,12 +154,10 @@ const UserPage = () => {
}
};
const handleFollowingEntityPaginate = (page: string | number) => {
setFollowingEntities((pre) => ({ ...pre, currPage: page as number }));
};
const handleOwnedEntityPaginate = (page: string | number) => {
setOwnedEntities((pre) => ({ ...pre, currPage: page as number }));
const handleEntityPaginate = (page: string | number) => {
history.push({
search: Qs.stringify({ page }),
});
};
const ErrorPlaceholder = () => {
@ -189,6 +200,7 @@ const UserPage = () => {
return (
<Users
followingEntities={followingEntities}
handlePaginate={handleEntityPaginate}
isAdminUser={Boolean(isAdminUser)}
isAuthDisabled={Boolean(isAuthDisabled)}
isLoggedinUser={isLoggedinUser(username)}
@ -197,8 +209,6 @@ const UserPage = () => {
updateUserDetails={updateUserDetails}
userData={userData}
username={username}
onFollowingEntityPaginate={handleFollowingEntityPaginate}
onOwnedEntityPaginate={handleOwnedEntityPaginate}
/>
);
} else {
@ -214,13 +224,13 @@ const UserPage = () => {
if (tab === UserProfileTab.FOLLOWING) {
fetchEntities(false, setFollowingEntities);
}
}, [followingEntities.currPage, tab, userData]);
}, [page, tab, userData]);
useEffect(() => {
if (tab === UserProfileTab.MY_DATA) {
fetchEntities(true, setOwnedEntities);
}
}, [ownedEntities.currPage, tab, userData]);
}, [page, tab, userData]);
useEffect(() => {
setCurrentLoggedInUser(AppState.getCurrentUserDetails());

View File

@ -0,0 +1,19 @@
/*
* 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 { SearchEntityHits } from 'utils/APIUtils';
export interface UserAssetsDataType {
data: SearchEntityHits;
total: number;
}

View File

@ -104,6 +104,7 @@ jest.mock('components/authentication/auth-provider/AuthProvider', () => {
});
jest.mock('react-router-dom', () => ({
useHistory: jest.fn(),
useParams: jest.fn().mockImplementation(() => ({ username: 'xyz' })),
useLocation: jest.fn().mockImplementation(() => new URLSearchParams()),
}));