diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Users/Users.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Users/Users.component.tsx index 9459df91417..2aed33c1527 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Users/Users.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Users/Users.component.tsx @@ -138,6 +138,8 @@ const Users = ({ const location = useLocation(); const isTaskType = isEqual(threadType, ThreadType.Task); const [isLoading, setIsLoading] = useState(false); + const [isRolesLoading, setIsRolesLoading] = useState(false); + const [isTeamsLoading, setIsTeamsLoading] = useState(false); const { authConfig } = useAuthContext(); const { t } = useTranslation(); @@ -161,21 +163,23 @@ const Users = ({ [threadType, fetchFeedHandler] ); - const fetchTeams = () => { - getTeams(['users']) - .then((res) => { - if (res.data) { - setTeams(res.data); - } else { - throw jsonData['api-error-messages']['unexpected-server-response']; - } - }) - .catch((err: AxiosError) => { - showErrorToast( - err, - jsonData['api-error-messages']['fetch-teams-error'] - ); - }); + const fetchTeams = async () => { + setIsTeamsLoading(true); + try { + const response = await getTeams(['users']); + if (response.data) { + setTeams(response.data); + } else { + throw jsonData['api-error-messages']['unexpected-server-response']; + } + } catch (error) { + showErrorToast( + error as AxiosError, + jsonData['api-error-messages']['fetch-teams-error'] + ); + } finally { + setIsTeamsLoading(false); + } }; const onDisplayNameChange = (e: React.ChangeEvent) => { @@ -484,6 +488,7 @@ const Users = ({ isSearchable aria-label="Select teams" className="tw-w-full" + isLoading={isTeamsLoading} options={teams?.map((team) => ({ label: getEntityName(team as unknown as EntityReference), value: team.id, @@ -624,6 +629,7 @@ const Users = ({ aria-label="Select roles" className="tw-w-full" id="select-role" + isLoading={isRolesLoading} options={userRolesOption} placeholder="Roles..." styles={reactSingleSelectCustomStyle} @@ -778,7 +784,7 @@ const Users = ({
{ + setIsRolesLoading(true); try { const response = await getRoles( '', @@ -882,6 +889,8 @@ const Users = ({ err as AxiosError, jsonData['api-error-messages']['fetch-roles-error'] ); + } finally { + setIsRolesLoading(false); } }; @@ -889,11 +898,6 @@ const Users = ({ fetchMoreFeed(isInView as boolean, paging, isFeedLoading); }, [isInView, paging, isFeedLoading]); - useEffect(() => { - fetchTeams(); - fetchRoles(); - }, []); - useEffect(() => { prepareSelectedRoles(); prepareSelectedTeams(); @@ -905,6 +909,18 @@ const Users = ({ } }, [image]); + useEffect(() => { + if (isRolesEdit && isEmpty(roles)) { + fetchRoles(); + } + }, [isRolesEdit, roles]); + + useEffect(() => { + if (isTeamsEdit && isEmpty(teams)) { + fetchTeams(); + } + }, [isTeamsEdit, teams]); + const getEntityData = useCallback( (tabNumber: number) => { const entityData = tabNumber === 3 ? ownedEntities : followingEntities; diff --git a/openmetadata-ui/src/main/resources/ui/src/enums/user.enum.ts b/openmetadata-ui/src/main/resources/ui/src/enums/user.enum.ts index bdbee1e27a2..69ddd39f1e2 100644 --- a/openmetadata-ui/src/main/resources/ui/src/enums/user.enum.ts +++ b/openmetadata-ui/src/main/resources/ui/src/enums/user.enum.ts @@ -26,3 +26,9 @@ export enum CreatePasswordGenerator { AutomaticGenerate = 'AUTOMATIC_GENERATE', CreatePassword = 'CREATE_PASSWORD', } +export enum UserProfileTab { + ACTIVITY = 'activity', + TASKS = 'tasks', + MY_DATA = 'mydata', + FOLLOWING = 'following', +} diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/UserPage/UserPage.component.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/UserPage/UserPage.component.tsx index a93e5cc40f2..6cbf6bafd17 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/UserPage/UserPage.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/UserPage/UserPage.component.tsx @@ -39,6 +39,7 @@ import { PAGE_SIZE } from '../../constants/constants'; import { myDataSearchIndex } from '../../constants/Mydata.constants'; import { getUserCurrentTab } from '../../constants/usersprofile.constants'; import { FeedFilter } from '../../enums/mydata.enum'; +import { UserProfileTab } from '../../enums/user.enum'; import { Post, Thread, @@ -54,7 +55,8 @@ import { showErrorToast } from '../../utils/ToastUtils'; const UserPage = () => { const { t } = useTranslation(); - const { username, tab } = useParams<{ [key: string]: string }>(); + const { username, tab = UserProfileTab.ACTIVITY } = + useParams<{ [key: string]: string }>(); const { search } = useLocation(); const { isAdminUser } = useAuth(); const { isAuthDisabled } = useAuthContext(); @@ -93,7 +95,7 @@ const UserPage = () => { const fetchUserData = () => { setUserData({} as User); - getUserByName(username, 'profile,roles,teams,follows,owns') + getUserByName(username, 'profile,roles,teams') .then((res) => { if (res) { setUserData(res); @@ -113,27 +115,29 @@ const UserPage = () => { .finally(() => setIsLoading(false)); }; - const fetchEntities = ( + const fetchEntities = async ( fetchOwnedEntities = false, handleEntity: Dispatch> ) => { const entity = fetchOwnedEntities ? ownedEntities : followingEntities; - searchData( - fetchOwnedEntities - ? `owner.id:${userData.id}` - : `followers:${userData.id}`, - entity.currPage, - PAGE_SIZE, - ``, - '', - '', - myDataSearchIndex - ) - .then((res) => { - const hits = res?.data?.hits?.hits as SearchEntityHits; + if (userData.id) { + try { + const response = await searchData( + fetchOwnedEntities + ? `owner.id:${userData.id}` + : `followers:${userData.id}`, + entity.currPage, + PAGE_SIZE, + ``, + '', + '', + myDataSearchIndex + ); + const hits = response.data.hits.hits as SearchEntityHits; + if (hits?.length > 0) { const data = formatDataResponse(hits); - const total = res.data.hits.total.value; + const total = response.data.hits.total.value; handleEntity({ data, total, @@ -148,15 +152,15 @@ const UserPage = () => { currPage: entity.currPage, }); } - }) - .catch((err: AxiosError) => { + } catch (error) { showErrorToast( - err, + error as AxiosError, t('server.entity-fetch-error', { entity: `${fetchOwnedEntities ? 'Owned' : 'Follwing'} Entities`, }) ); - }); + } + } }; const handleFollowingEntityPaginate = (page: string | number) => { @@ -338,7 +342,13 @@ const UserPage = () => { }, [username]); useEffect(() => { - if (userData.id) { + const isActivityTabs = [ + UserProfileTab.ACTIVITY, + UserProfileTab.TASKS, + ].includes(tab as UserProfileTab); + + // only make feed api call if active tab is either activity or tasks + if (userData.id && isActivityTabs) { const threadType = tab === 'tasks' ? ThreadType.Task : ThreadType.Conversation; @@ -358,19 +368,16 @@ const UserPage = () => { }, [tab]); useEffect(() => { - if (!isEmpty(userData)) { - fetchEntities(true, setOwnedEntities); + if (tab === UserProfileTab.FOLLOWING) { fetchEntities(false, setFollowingEntities); } - }, [userData]); + }, [followingEntities.currPage, tab, userData]); useEffect(() => { - fetchEntities(false, setFollowingEntities); - }, [followingEntities.currPage]); - - useEffect(() => { - fetchEntities(true, setOwnedEntities); - }, [ownedEntities.currPage]); + if (tab === UserProfileTab.MY_DATA) { + fetchEntities(true, setOwnedEntities); + } + }, [ownedEntities.currPage, tab, userData]); useEffect(() => { setCurrentLoggedInUser(AppState.getCurrentUserDetails());