mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-06-27 04:22:05 +00:00
supported rendering all suggestion on user avatar click
This commit is contained in:
parent
c77f6d5db6
commit
efb99c2889
@ -30,6 +30,7 @@ export interface SuggestionsContextType {
|
||||
allSuggestionsUsers: EntityReference[];
|
||||
onUpdateActiveUser: (user?: EntityReference) => void;
|
||||
fetchSuggestions: () => void;
|
||||
fetchSuggestionsByUserId: (userId: string, limit?: number) => void;
|
||||
acceptRejectSuggestion: (
|
||||
suggestion: Suggestion,
|
||||
action: SuggestionAction
|
||||
|
@ -45,6 +45,7 @@ jest.mock('../../../hooks/useFqn', () => ({
|
||||
|
||||
jest.mock('../../../rest/suggestionsAPI', () => ({
|
||||
getSuggestionsList: jest.fn().mockImplementation(() => Promise.resolve()),
|
||||
getSuggestionsByUserId: jest.fn().mockImplementation(() => Promise.resolve()),
|
||||
approveRejectAllSuggestions: jest.fn(),
|
||||
updateSuggestionStatus: jest.fn(),
|
||||
}));
|
||||
@ -144,6 +145,26 @@ describe('SuggestionsProvider', () => {
|
||||
SuggestionAction.Reject
|
||||
);
|
||||
});
|
||||
|
||||
it('calls fetchSuggestionsByUserId when button is clicked', async () => {
|
||||
const { getSuggestionsByUserId } = await import(
|
||||
'../../../rest/suggestionsAPI'
|
||||
);
|
||||
|
||||
render(
|
||||
<SuggestionsProvider>
|
||||
<TestComponent />
|
||||
</SuggestionsProvider>
|
||||
);
|
||||
|
||||
const fetchByUserIdBtn = screen.getByText('Fetch By User ID');
|
||||
fireEvent.click(fetchByUserIdBtn);
|
||||
|
||||
expect(getSuggestionsByUserId).toHaveBeenCalledWith('test-user-id', {
|
||||
entityFQN: 'mockFQN',
|
||||
limit: 10,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function TestComponent() {
|
||||
@ -151,6 +172,7 @@ function TestComponent() {
|
||||
acceptRejectAllSuggestions,
|
||||
onUpdateActiveUser,
|
||||
acceptRejectSuggestion,
|
||||
fetchSuggestionsByUserId,
|
||||
} = useSuggestionsContext();
|
||||
|
||||
return (
|
||||
@ -181,6 +203,9 @@ function TestComponent() {
|
||||
}>
|
||||
Reject One
|
||||
</button>
|
||||
<button onClick={() => fetchSuggestionsByUserId('test-user-id')}>
|
||||
Fetch By User ID
|
||||
</button>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ import { useFqn } from '../../../hooks/useFqn';
|
||||
import { usePub } from '../../../hooks/usePubSub';
|
||||
import {
|
||||
approveRejectAllSuggestions,
|
||||
getSuggestionsByUserId,
|
||||
getSuggestionsList,
|
||||
updateSuggestionStatus,
|
||||
} from '../../../rest/suggestionsAPI';
|
||||
@ -97,6 +98,43 @@ const SuggestionsProvider = ({ children }: { children?: ReactNode }) => {
|
||||
[entityFqn, suggestionLimit]
|
||||
);
|
||||
|
||||
const fetchSuggestionsByUserId = useCallback(
|
||||
async (userId: string, limit?: number) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const { data } = await getSuggestionsByUserId(userId, {
|
||||
entityFQN: entityFqn,
|
||||
limit: limit ?? suggestionLimit,
|
||||
});
|
||||
|
||||
// Merge new suggestions with existing ones, removing duplicates by ID
|
||||
setSuggestions((prevSuggestions) => {
|
||||
const existingIds = new Set(prevSuggestions.map((s) => s.id));
|
||||
const newSuggestions = data.filter((s) => !existingIds.has(s.id));
|
||||
const mergedSuggestions = [...prevSuggestions, ...newSuggestions];
|
||||
|
||||
// Update grouped suggestions with merged data
|
||||
const { allUsersList, groupedSuggestions } =
|
||||
getSuggestionByType(mergedSuggestions);
|
||||
setAllSuggestionsUsers(uniqWith(allUsersList, isEqual));
|
||||
setSuggestionsByUser(groupedSuggestions);
|
||||
|
||||
return mergedSuggestions;
|
||||
});
|
||||
} catch (err) {
|
||||
showErrorToast(
|
||||
err as AxiosError,
|
||||
t('server.entity-fetch-error', {
|
||||
entity: t('label.suggestion-lowercase-plural'),
|
||||
})
|
||||
);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
},
|
||||
[entityFqn, suggestionLimit]
|
||||
);
|
||||
|
||||
const acceptRejectSuggestion = useCallback(
|
||||
async (suggestion: Suggestion, status: SuggestionAction) => {
|
||||
try {
|
||||
@ -188,6 +226,7 @@ const SuggestionsProvider = ({ children }: { children?: ReactNode }) => {
|
||||
allSuggestionsUsers,
|
||||
onUpdateActiveUser,
|
||||
fetchSuggestions,
|
||||
fetchSuggestionsByUserId,
|
||||
acceptRejectSuggestion,
|
||||
acceptRejectAllSuggestions,
|
||||
};
|
||||
@ -203,6 +242,7 @@ const SuggestionsProvider = ({ children }: { children?: ReactNode }) => {
|
||||
allSuggestionsUsers,
|
||||
onUpdateActiveUser,
|
||||
fetchSuggestions,
|
||||
fetchSuggestionsByUserId,
|
||||
acceptRejectSuggestion,
|
||||
acceptRejectAllSuggestions,
|
||||
]);
|
||||
|
@ -13,6 +13,7 @@
|
||||
import { render } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { EntityReference } from '../../../generated/entity/type';
|
||||
import { useSuggestionsContext } from '../../Suggestions/SuggestionsProvider/SuggestionsProvider';
|
||||
import AvatarCarouselItem from './AvatarCarouselItem';
|
||||
|
||||
const suggestions = [
|
||||
@ -46,6 +47,7 @@ jest.mock('../../Suggestions/SuggestionsProvider/SuggestionsProvider', () => ({
|
||||
acceptRejectSuggestion: jest.fn(),
|
||||
selectedUserSuggestions: [],
|
||||
onUpdateActiveUser: jest.fn(),
|
||||
fetchSuggestionsByUserId: jest.fn(),
|
||||
})),
|
||||
__esModule: true,
|
||||
default: 'SuggestionsProvider',
|
||||
@ -101,6 +103,37 @@ describe('AvatarCarouselItem', () => {
|
||||
expect(onAvatarClick).toHaveBeenCalledWith(index);
|
||||
});
|
||||
|
||||
it('calls fetchSuggestionsByUserId when avatar is clicked', () => {
|
||||
const mockFetchSuggestionsByUserId = jest.fn();
|
||||
(useSuggestionsContext as jest.Mock).mockImplementation(() => ({
|
||||
suggestions: suggestions,
|
||||
suggestionsByUser: suggByUser,
|
||||
allSuggestionsUsers: [
|
||||
{ id: '1', name: 'Avatar 1', type: 'user' },
|
||||
{ id: '2', name: 'Avatar 2', type: 'user' },
|
||||
],
|
||||
acceptRejectSuggestion: jest.fn(),
|
||||
selectedUserSuggestions: [],
|
||||
onUpdateActiveUser: jest.fn(),
|
||||
fetchSuggestionsByUserId: mockFetchSuggestionsByUserId,
|
||||
}));
|
||||
|
||||
const { getByTestId } = render(
|
||||
<AvatarCarouselItem
|
||||
avatar={avatar}
|
||||
avatarBtnRefs={avatarBtnRefs}
|
||||
index={index}
|
||||
isActive={isActive}
|
||||
onAvatarClick={onAvatarClick}
|
||||
/>
|
||||
);
|
||||
|
||||
const button = getByTestId(`avatar-carousel-item-${avatar.id}`);
|
||||
button.click();
|
||||
|
||||
expect(mockFetchSuggestionsByUserId).toHaveBeenCalledWith(avatar.id);
|
||||
});
|
||||
|
||||
it('sets isActive class when isActive is true', () => {
|
||||
const { getByTestId } = render(
|
||||
<AvatarCarouselItem
|
||||
|
@ -33,7 +33,8 @@ const AvatarCarouselItem = ({
|
||||
onAvatarClick,
|
||||
isActive,
|
||||
}: AvatarCarouselItemProps) => {
|
||||
const { suggestionsByUser } = useSuggestionsContext();
|
||||
const { suggestionsByUser, fetchSuggestionsByUserId } =
|
||||
useSuggestionsContext();
|
||||
const buttonRef = useRef(null);
|
||||
avatarBtnRefs.current[index] = buttonRef;
|
||||
const getUserSuggestionsCount = useCallback(
|
||||
@ -42,6 +43,16 @@ const AvatarCarouselItem = ({
|
||||
[suggestionsByUser]
|
||||
);
|
||||
|
||||
const handleAvatarClick = useCallback(() => {
|
||||
// Call the original onAvatarClick function
|
||||
onAvatarClick(index);
|
||||
|
||||
// Fetch suggestions for this specific user
|
||||
if (avatar.id) {
|
||||
fetchSuggestionsByUserId(avatar.id);
|
||||
}
|
||||
}, [onAvatarClick, index, avatar.id, fetchSuggestionsByUserId]);
|
||||
|
||||
const button = (
|
||||
<Button
|
||||
className={classNames('p-0 m-r-xss avatar-item', {
|
||||
@ -50,7 +61,7 @@ const AvatarCarouselItem = ({
|
||||
data-testid={`avatar-carousel-item-${avatar.id}`}
|
||||
ref={buttonRef}
|
||||
shape="circle"
|
||||
onClick={() => onAvatarClick(index)}>
|
||||
onClick={handleAvatarClick}>
|
||||
<ProfilePicture name={avatar.name ?? ''} width="28" />
|
||||
</Button>
|
||||
);
|
||||
|
@ -25,6 +25,7 @@ const BASE_URL = '/suggestions';
|
||||
export type ListSuggestionsParams = ListParams & {
|
||||
entityFQN?: string;
|
||||
limit?: number;
|
||||
userId?: string;
|
||||
};
|
||||
|
||||
export const getSuggestionsList = async (params?: ListSuggestionsParams) => {
|
||||
@ -35,6 +36,20 @@ export const getSuggestionsList = async (params?: ListSuggestionsParams) => {
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const getSuggestionsByUserId = async (
|
||||
userId: string,
|
||||
params?: Omit<ListSuggestionsParams, 'userId'>
|
||||
) => {
|
||||
const response = await APIClient.get<PagingResponse<Suggestion[]>>(BASE_URL, {
|
||||
params: {
|
||||
...params,
|
||||
userId,
|
||||
},
|
||||
});
|
||||
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const updateSuggestionStatus = (
|
||||
data: Suggestion,
|
||||
action: SuggestionAction
|
||||
|
Loading…
x
Reference in New Issue
Block a user