From 5acb443d4a91a2bdccb200c00ad3f34142acbc95 Mon Sep 17 00:00:00 2001 From: darth-coder00 <86726556+darth-coder00@users.noreply.github.com> Date: Tue, 17 May 2022 11:20:49 +0530 Subject: [PATCH] UI: Add support for User's profile image everywhere (#4856) --- .../src/main/resources/ui/src/AppState.ts | 147 +++++++++++++++++- .../resources/ui/src/axiosAPIs/userAPI.ts | 13 +- .../FeedCardFooter/FeedCardFooter.test.tsx | 6 +- .../FeedCardFooter/FeedCardFooter.tsx | 6 +- .../FeedCardHeader/FeedCardHeader.test.tsx | 4 +- .../FeedCardHeader/FeedCardHeader.tsx | 6 +- .../DashboardDetails.component.tsx | 6 +- .../DashboardVersion.component.tsx | 3 + .../DatasetDetails.component.tsx | 2 + .../DatasetVersion.component.tsx | 3 + .../GlossaryDetails.component.tsx | 8 +- .../GlossaryDetails/GlossaryDetails.test.tsx | 4 + .../RelatedTermsModal/RelatedTermsModal.tsx | 3 +- .../ReviewerModal/ReviewerModal.component.tsx | 4 +- .../PipelineDetails.component.tsx | 6 +- .../PipelineVersion.component.tsx | 3 + .../components/TeamDetails/TeamDetails.tsx | 4 + .../TopicDetails/TopicDetails.component.tsx | 6 +- .../TopicVersion/TopicVersion.component.tsx | 3 + .../UserDataCard/UserDataCard.test.tsx | 10 +- .../components/UserDataCard/UserDataCard.tsx | 20 ++- .../components/UserDetails/UserDetails.tsx | 2 +- .../ui/src/components/UserList/UserList.tsx | 2 +- .../components/Users/Users.component.test.tsx | 4 +- .../src/components/Users/Users.component.tsx | 9 +- .../ProfilePicture/ProfilePicture.test.tsx | 78 ++++++++++ .../common/ProfilePicture/ProfilePicture.tsx | 101 ++++++++++++ .../src/components/common/avatar/Avatar.tsx | 3 +- .../entityPageInfo/EntityPageInfo.test.tsx | 4 +- .../common/entityPageInfo/EntityPageInfo.tsx | 8 +- .../common/table-data-card/TableDataCard.tsx | 14 +- .../ui/src/components/nav-bar/NavBar.tsx | 3 +- .../components/searched-data/SearchedData.tsx | 2 +- .../tags-container/tags-container.test.tsx | 10 ++ .../resources/ui/src/constants/constants.ts | 1 + .../resources/ui/src/interface/types.d.ts | 3 + .../DatabaseSchemaPage.component.tsx | 5 + .../ui/src/pages/database-details/index.tsx | 5 + .../resources/ui/src/pages/service/index.tsx | 5 + .../ui/src/pages/teams/CheckboxUserCard.tsx | 18 ++- .../ui/src/pages/teams/UserCard.test.tsx | 8 +- .../resources/ui/src/pages/teams/UserCard.tsx | 8 +- .../resources/ui/src/pages/teams/index.tsx | 5 + .../src/main/resources/ui/src/styles/temp.css | 11 +- .../resources/ui/src/utils/CommonUtils.tsx | 2 +- .../resources/ui/src/utils/EntityUtils.tsx | 9 +- .../resources/ui/src/utils/UserDataUtils.ts | 56 ++++++- 47 files changed, 565 insertions(+), 78 deletions(-) create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/common/ProfilePicture/ProfilePicture.test.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/common/ProfilePicture/ProfilePicture.tsx 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 = ({
- +