diff --git a/openmetadata-ui/src/main/resources/ui/src/components/ManageTab/ManageTab.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/ManageTab/ManageTab.component.tsx index e31ff371e0d..8e7a9c36b12 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/ManageTab/ManageTab.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/ManageTab/ManageTab.component.tsx @@ -180,13 +180,11 @@ const ManageTab: FunctionComponent = ({ const getOwnerSuggestion = useCallback( (qSearchText = '') => { setIsUserLoading(true); + setListOwners([]); suggestFormattedUsersAndTeams(qSearchText) .then((res) => { const { users, teams } = res; - setListOwners(getOwnerList(users, teams)); - }) - .catch(() => { - setListOwners([]); + setListOwners(getOwnerList(users, teams, true)); }) .finally(() => { setIsUserLoading(false); diff --git a/openmetadata-ui/src/main/resources/ui/src/components/common/OwnerWidget/OwnerWidget.tsx b/openmetadata-ui/src/main/resources/ui/src/components/common/OwnerWidget/OwnerWidget.tsx index 207d7a8ec63..3790d598ea9 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/common/OwnerWidget/OwnerWidget.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/common/OwnerWidget/OwnerWidget.tsx @@ -12,15 +12,20 @@ */ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { AxiosError } from 'axios'; import classNames from 'classnames'; import { isUndefined, lowerCase } from 'lodash'; -import React, { Fragment } from 'react'; +import React, { Fragment, useEffect, useState } from 'react'; +import { getTeams } from '../../../axiosAPIs/teamsAPI'; +import { getUsers } from '../../../axiosAPIs/userAPI'; import { ADMIN_ONLY_ACCESSIBLE_SECTION } from '../../../enums/common.enum'; import { Operation } from '../../../generated/entity/policies/policy'; import { EntityReference } from '../../../generated/type/entityReference'; import { useAuth } from '../../../hooks/authHooks'; +import jsonData from '../../../jsons/en'; import { hasEditAccess } from '../../../utils/CommonUtils'; import { getTitleCase } from '../../../utils/EntityUtils'; +import { showErrorToast } from '../../../utils/ToastUtils'; import { isCurrentUserAdmin } from '../../../utils/UserDataUtils'; import { Button } from '../../buttons/Button/Button'; import DropDownList from '../../dropdown/DropDownList'; @@ -78,11 +83,50 @@ const OwnerWidget = ({ handleSearchOwnerDropdown, }: OwnerWidgetProps) => { const { userPermissions, isAdminUser } = useAuth(); - + const [totalUsersCount, setTotalUsersCount] = useState(0); + const [totalTeamsCount, setTotalTeamsCount] = useState(0); const getOwnerGroup = () => { return allowTeamOwner ? ['Teams', 'Users'] : ['Users']; }; + const fetchTeamsAndUsersCount = () => { + getUsers('', 0) + .then((res) => { + if (res.data) { + setTotalUsersCount(res.data.paging.total); + } else { + throw jsonData['api-error-messages']['unexpected-server-response']; + } + }) + .catch((err: AxiosError) => { + showErrorToast( + err, + jsonData['api-error-messages']['unexpected-server-response'] + ); + setTotalTeamsCount(0); + }); + + getTeams('', 0) + .then((res) => { + if (res.data) { + setTotalTeamsCount(res.data.paging.total); + } else { + throw jsonData['api-error-messages']['unexpected-server-response']; + } + }) + .catch((err: AxiosError) => { + showErrorToast( + err, + jsonData['api-error-messages']['unexpected-server-response'] + ); + setTotalTeamsCount(0); + }); + }; + + useEffect(() => { + fetchTeamsAndUsersCount(); + }, []); + const getOwnerUpdateLoader = () => { switch (statusOwner) { case 'waiting': @@ -128,6 +172,16 @@ const OwnerWidget = ({ ? 'The owner of the team can manage the team by adding or removing users. Add or update Team ownership here' : `Add or update ${getTitleCase(entityType)} ownership here`; + const handleTotalCountForGroup = (groupName: string) => { + if (lowerCase(groupName) === 'users') { + return totalUsersCount; + } else if (lowerCase(groupName) === 'teams') { + return totalTeamsCount; + } else { + return 0; + } + }; + return (
@@ -177,6 +231,7 @@ const OwnerWidget = ({ showEmptyList controlledSearchStr={ownerSearchText} dropDownList={listOwners} + getTotalCountForGroup={handleTotalCountForGroup} groupType="tab" isLoading={isListLoading} listGroups={getOwnerGroup()} diff --git a/openmetadata-ui/src/main/resources/ui/src/components/dropdown/DropDownList.tsx b/openmetadata-ui/src/main/resources/ui/src/components/dropdown/DropDownList.tsx index d377422160e..ea71c63b3ba 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/dropdown/DropDownList.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/dropdown/DropDownList.tsx @@ -36,6 +36,7 @@ const DropDownList: FunctionComponent = ({ domPosition, className = '', widthClass = 'tw-w-52', + getTotalCountForGroup, }: DropDownListProp) => { const { height: windowHeight } = useWindowDimensions(); const isMounted = useRef(false); @@ -89,6 +90,17 @@ const DropDownList: FunctionComponent = ({ }); }; + const getGroupCount = (groupName?: string): number => { + let count = 0; + if (controlledSearchStr === '' && getTotalCountForGroup && groupName) { + count = getTotalCountForGroup(groupName); + } else { + count = getSearchedListByGroup(groupName)?.length; + } + + return count; + }; + const getDropDownElement = (item: DropDownListItem, index: number) => { return (
= ({ onClick={() => setActiveTab(index + 1)}> {grp} {getCountBadge( - getSearchedListByGroup(grp).length, + getGroupCount(grp), '', activeTab === index + 1 )} diff --git a/openmetadata-ui/src/main/resources/ui/src/components/dropdown/types.ts b/openmetadata-ui/src/main/resources/ui/src/components/dropdown/types.ts index e747b9885c8..c79807a0761 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/dropdown/types.ts +++ b/openmetadata-ui/src/main/resources/ui/src/components/dropdown/types.ts @@ -59,6 +59,7 @@ export type DropDownListProp = { domPosition?: DOMRect; isLoading?: boolean; widthClass?: string; + getTotalCountForGroup?: (groupName: string) => number; }; export type DropDownProp = { diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/ManageUtils.ts b/openmetadata-ui/src/main/resources/ui/src/utils/ManageUtils.ts index f641a35443c..80a01c5870e 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/ManageUtils.ts +++ b/openmetadata-ui/src/main/resources/ui/src/utils/ManageUtils.ts @@ -16,9 +16,16 @@ import AppState from '../AppState'; import { EntityReference } from '../generated/type/entityUsage'; import { getEntityName } from './CommonUtils'; +/** + * @param listUsers - List of users + * @param listTeams - List of teams + * @param excludeCurrentUser - Wether to exclude current user to be on list. Needed when calls from searching + * @returns List of user or team + */ export const getOwnerList = ( listUsers?: FormattedUsersData[], - listTeams?: FormattedTeamsData[] + listTeams?: FormattedTeamsData[], + excludeCurrentUser?: boolean ) => { const userDetails = AppState.getCurrentUserDetails(); @@ -47,17 +54,21 @@ export const getOwnerList = ( })); return [ - { - name: getEntityName(userDetails as unknown as EntityReference), - value: userDetails.id, - group: 'Users', - type: 'user', - }, + ...(!excludeCurrentUser + ? [ + { + name: getEntityName(userDetails as unknown as EntityReference), + value: userDetails.id, + group: 'Users', + type: 'user', + }, + ] + : []), ...users, ...teams, ]; } else { - return userDetails + return userDetails && !excludeCurrentUser ? [ { name: getEntityName(userDetails as unknown as EntityReference),