diff --git a/openmetadata-ui/src/main/resources/ui/src/AppState.ts b/openmetadata-ui/src/main/resources/ui/src/AppState.ts index 733bd4eafc4..bbf6fc1a5e3 100644 --- a/openmetadata-ui/src/main/resources/ui/src/AppState.ts +++ b/openmetadata-ui/src/main/resources/ui/src/AppState.ts @@ -11,15 +11,18 @@ * limitations under the License. */ -import { isEmpty, isNil } from 'lodash'; +import { isEmpty, isNil, isUndefined } from 'lodash'; import { action, makeAutoObservable } from 'mobx'; import { ClientAuth, NewUser, UserPermissions } from 'Models'; +import { reactLocalStorage } from 'reactjs-localstorage'; +import { LOCALSTORAGE_USER_PROFILES } from './constants/constants'; import { CurrentTourPageType } from './enums/tour.enum'; import { Role } from './generated/entity/teams/role'; import { EntityReference as UserTeams, User, } from './generated/entity/teams/user'; +import { ImageList } from './generated/type/profile'; class AppState { users: Array = []; @@ -36,6 +39,15 @@ class AppState { userTeams: Array = []; userRoles: Array = []; userPermissions: UserPermissions = {} as UserPermissions; + userProfilePics: Array<{ + id: string; + name: string; + profile: ImageList['image512']; + }> = []; + userProfilePicsLoading: Array<{ + id: string; + name: string; + }> = []; inPageSearchText = ''; explorePageTab = 'tables'; @@ -60,6 +72,13 @@ class AppState { getAllTeams: action, getAllRoles: action, getAllPermissions: action, + getUserProfilePic: action, + updateUserProfilePic: action, + loadUserProfilePics: action, + getProfilePicsLoading: action, + updateProfilePicsLoading: action, + isProfilePicLoading: action, + removeProfilePicsLoading: action, }); } @@ -96,6 +115,98 @@ class AppState { this.explorePageTab = tab; } + updateUserProfilePic( + id?: string, + username?: string, + profile?: ImageList['image512'] + ) { + if (!id && !username) { + return; + } + + const filteredList = this.userProfilePics.filter((item) => { + // compare id only if present + if (item.id && id) { + return item.id !== id; + } else { + return item.name !== username; + } + }); + this.userProfilePics = [ + ...filteredList, + { + id: id || '', + name: username || '', + profile, + }, + ]; + + reactLocalStorage.setObject(LOCALSTORAGE_USER_PROFILES, { + data: this.userProfilePics, + }); + + return profile; + } + + updateProfilePicsLoading(id?: string, username?: string) { + if (!id && !username) { + return; + } + + const alreadyLoading = !isUndefined( + this.userProfilePicsLoading.find((loadingItem) => { + // compare id only if present + if (loadingItem.id && id) { + return loadingItem.id === id; + } else { + return loadingItem.name === username; + } + }) + ); + + if (!alreadyLoading) { + this.userProfilePicsLoading = [ + ...this.userProfilePicsLoading, + { + id: id || '', + name: username || '', + }, + ]; + } + } + + removeProfilePicsLoading(id?: string, username?: string) { + if (!id && !username) { + return; + } + + const filteredList = this.userProfilePicsLoading.filter((loadingItem) => { + // compare id only if present + if (loadingItem.id && id) { + return loadingItem.id !== id; + } else { + return loadingItem.name !== username; + } + }); + + this.userProfilePicsLoading = filteredList; + } + + loadUserProfilePics() { + const { data } = reactLocalStorage.getObject( + LOCALSTORAGE_USER_PROFILES + ) as { + data: Array<{ + id: string; + name: string; + profile: ImageList['image512']; + }>; + }; + if (data) { + this.userProfilePics = data; + } + } + getCurrentUserDetails() { if (!isEmpty(this.userDetails) && !isNil(this.userDetails)) { return this.userDetails; @@ -109,6 +220,40 @@ class AppState { } } + getUserProfilePic(id?: string, username?: string) { + const data = this.userProfilePics.find((item) => { + // compare id only if present + if (item.id && id) { + return item.id === id; + } else { + return item.name === username; + } + }); + + return data?.profile; + } + + getAllUserProfilePics() { + return this.userProfilePics; + } + + getProfilePicsLoading() { + return this.userProfilePicsLoading; + } + + isProfilePicLoading(id?: string, username?: string) { + const data = this.userProfilePicsLoading.find((loadingPic) => { + // compare id only if present + if (loadingPic.id && id) { + return loadingPic.id === id; + } else { + return loadingPic.name === username; + } + }); + + return Boolean(data); + } + getAllUsers() { return this.users; } diff --git a/openmetadata-ui/src/main/resources/ui/src/axiosAPIs/userAPI.ts b/openmetadata-ui/src/main/resources/ui/src/axiosAPIs/userAPI.ts index 61d5b2e1dce..6d84d8a0411 100644 --- a/openmetadata-ui/src/main/resources/ui/src/axiosAPIs/userAPI.ts +++ b/openmetadata-ui/src/main/resources/ui/src/axiosAPIs/userAPI.ts @@ -64,6 +64,15 @@ export const getUserByName = ( return APIClient.get(url); }; +export const getUserById = ( + id: string, + arrQueryFields?: string +): Promise => { + const url = getURLWithQueryFields(`/users/${id}`, arrQueryFields); + + return APIClient.get(url); +}; + export const getLoggedInUser = (arrQueryFields?: string) => { const url = getURLWithQueryFields('/users/loggedInUser', arrQueryFields); @@ -98,10 +107,6 @@ export const updateUserTeam: Function = ( return APIClient.post(`/users/${id}/teams`, options); }; -export const getUserById: Function = (id: string): Promise => { - return APIClient.get(`/users/${id}`); -}; - export const createUser = ( userDetails: Record | UserProfile> | CreateUser ): Promise => { diff --git a/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/FeedCardFooter/FeedCardFooter.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/FeedCardFooter/FeedCardFooter.test.tsx index 838d99a4fff..34324788858 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/FeedCardFooter/FeedCardFooter.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/FeedCardFooter/FeedCardFooter.test.tsx @@ -30,8 +30,10 @@ jest.mock('../../../utils/TimeUtils', () => ({ getDayTimeByTimeStamp: jest.fn(), })); -jest.mock('../../common/avatar/Avatar', () => { - return jest.fn().mockReturnValue(

Avatar

); +jest.mock('../../common/ProfilePicture/ProfilePicture', () => { + return jest + .fn() + .mockReturnValue(

ProfilePicture

); }); const mockFeedCardFooterPorps = { diff --git a/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/FeedCardFooter/FeedCardFooter.tsx b/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/FeedCardFooter/FeedCardFooter.tsx index 3d6c8d85e05..bcda58216a4 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/FeedCardFooter/FeedCardFooter.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/FeedCardFooter/FeedCardFooter.tsx @@ -15,7 +15,7 @@ import { isUndefined, toLower } from 'lodash'; import React, { FC } from 'react'; import { getReplyText } from '../../../utils/FeedUtils'; import { getDayTimeByTimeStamp } from '../../../utils/TimeUtils'; -import Avatar from '../../common/avatar/Avatar'; +import ProfilePicture from '../../common/ProfilePicture/ProfilePicture'; import { FeedFooterProp } from '../ActivityFeedCard/ActivityFeedCard.interface'; const FeedCardFooter: FC = ({ @@ -36,12 +36,12 @@ const FeedCardFooter: FC = ({ isFooterVisible ? (
{repliedUsers?.map((u, i) => ( - ))} diff --git a/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/FeedCardHeader/FeedCardHeader.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/FeedCardHeader/FeedCardHeader.test.tsx index 06f8e67e08f..b7fa4e2a5cd 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/FeedCardHeader/FeedCardHeader.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/FeedCardHeader/FeedCardHeader.test.tsx @@ -39,8 +39,8 @@ jest.mock('../../../utils/TimeUtils', () => ({ getDayTimeByTimeStamp: jest.fn(), })); -jest.mock('../../common/avatar/Avatar', () => { - return jest.fn().mockReturnValue(

Avatar

); +jest.mock('../../common/ProfilePicture/ProfilePicture', () => { + return jest.fn().mockReturnValue(

ProfilePicture

); }); const mockFeedHeaderProps = { diff --git a/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/FeedCardHeader/FeedCardHeader.tsx b/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/FeedCardHeader/FeedCardHeader.tsx index 9130a3524fc..6b7ac630e4c 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/FeedCardHeader/FeedCardHeader.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/FeedCardHeader/FeedCardHeader.tsx @@ -38,8 +38,8 @@ import SVGIcons, { Icons } from '../../../utils/SvgUtils'; import { getEntityLink } from '../../../utils/TableUtils'; import { getDayTimeByTimeStamp } from '../../../utils/TimeUtils'; import { Button } from '../../buttons/Button/Button'; -import Avatar from '../../common/avatar/Avatar'; import PopOver from '../../common/popover/PopOver'; +import ProfilePicture from '../../common/ProfilePicture/ProfilePicture'; import Loader from '../../Loader/Loader'; import { FeedHeaderProp } from '../ActivityFeedCard/ActivityFeedCard.interface'; import './FeedCardHeader.style.css'; @@ -92,7 +92,7 @@ const FeedCardHeader: FC = ({
- +