-
-
Notifications
You must be signed in to change notification settings - Fork 844
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[FIX] Figma User Portal: Organization Left Drawer Violates The Figma …
…Style Guide (#3421) * UI fix UserSidebarOrg * fix * Update src/components/ProfileDropdown/ProfileDropdown.tsx Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Update src/components/ProfileDropdown/ProfileDropdown.tsx Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Update src/components/ProfileCard/ProfileCard.spec.tsx Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Update src/components/SignOut/SignOut.tsx Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Update src/components/ProfileCard/ProfileCard.spec.tsx Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * fix --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
- Loading branch information
1 parent
45b332c
commit 00fe16b
Showing
12 changed files
with
1,058 additions
and
382 deletions.
There are no files selected for viewing
23 changes: 23 additions & 0 deletions
23
docs/docs/auto-docs/components/ProfileCard/ProfileCard/functions/default.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
[Admin Docs](/) | ||
|
||
*** | ||
|
||
# Function: default() | ||
|
||
> **default**(): `Element` | ||
Defined in: [src/components/ProfileCard/ProfileCard.tsx:21](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/components/ProfileCard/ProfileCard.tsx#L21) | ||
|
||
Renders a profile card for the user. | ||
|
||
This component displays the user's profile picture or an avatar, their name (truncated if necessary), | ||
and their role (SuperAdmin, Admin, or User). It provides options to view the profile. | ||
|
||
- If a user image is available, it displays that; otherwise, it shows an avatar. | ||
- The displayed name is truncated if it exceeds a specified length. | ||
|
||
## Returns | ||
|
||
`Element` | ||
|
||
JSX.Element - The profile card . |
20 changes: 20 additions & 0 deletions
20
docs/docs/auto-docs/components/SignOut/SignOut/functions/default.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
[Admin Docs](/) | ||
|
||
*** | ||
|
||
# Function: default() | ||
|
||
> **default**(): `Element` | ||
Defined in: [src/components/SignOut/SignOut.tsx:20](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/components/SignOut/SignOut.tsx#L20) | ||
|
||
Renders a sign out button. | ||
|
||
This component helps to logout. | ||
The logout function revokes the refresh token and clears local storage before redirecting to the home page. | ||
|
||
## Returns | ||
|
||
`Element` | ||
|
||
JSX.Element - The profile card . |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,191 @@ | ||
import React, { act } from 'react'; | ||
import { render, screen } from '@testing-library/react'; | ||
import userEvent from '@testing-library/user-event'; | ||
import { BrowserRouter, Route, Routes } from 'react-router-dom'; | ||
import ProfileCard from './ProfileCard'; | ||
import { MockedProvider } from '@apollo/react-testing'; | ||
import { REVOKE_REFRESH_TOKEN } from 'GraphQl/Mutations/mutations'; | ||
import useLocalStorage from 'utils/useLocalstorage'; | ||
import { I18nextProvider } from 'react-i18next'; | ||
import i18nForTest from 'utils/i18nForTest'; | ||
import { GET_COMMUNITY_SESSION_TIMEOUT_DATA } from 'GraphQl/Queries/Queries'; | ||
import { vi } from 'vitest'; | ||
|
||
const { setItem } = useLocalStorage(); | ||
|
||
const mockNavigate = vi.fn(); | ||
|
||
// Mock useNavigate hook | ||
vi.mock('react-router-dom', async () => { | ||
const actual = await vi.importActual('react-router-dom'); | ||
return { | ||
...actual, | ||
useNavigate: () => mockNavigate, | ||
}; | ||
}); | ||
|
||
const MOCKS = [ | ||
{ | ||
request: { | ||
query: REVOKE_REFRESH_TOKEN, | ||
}, | ||
result: { | ||
data: { | ||
revokeRefreshTokenForUser: true, | ||
}, | ||
}, | ||
}, | ||
{ | ||
request: { | ||
query: GET_COMMUNITY_SESSION_TIMEOUT_DATA, | ||
}, | ||
result: { | ||
data: { | ||
getCommunityData: { | ||
timeout: 30, | ||
}, | ||
}, | ||
}, | ||
delay: 1000, | ||
}, | ||
]; | ||
|
||
vi.mock('react-toastify', () => ({ | ||
toast: { | ||
success: vi.fn(), | ||
warn: vi.fn(), | ||
error: vi.fn(), | ||
}, | ||
clear: vi.fn(), | ||
})); | ||
|
||
beforeEach(() => { | ||
setItem('FirstName', 'John'); | ||
setItem('LastName', 'Doe'); | ||
setItem( | ||
'UserImage', | ||
'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe', | ||
); | ||
setItem('SuperAdmin', false); | ||
setItem('AdminFor', []); | ||
setItem('id', '123'); | ||
}); | ||
|
||
afterEach(() => { | ||
vi.clearAllMocks(); | ||
localStorage.clear(); | ||
}); | ||
|
||
describe('ProfileDropdown Component', () => { | ||
test('renders with user information', () => { | ||
render( | ||
<MockedProvider mocks={MOCKS} addTypename={false}> | ||
<BrowserRouter> | ||
<I18nextProvider i18n={i18nForTest}> | ||
<ProfileCard /> | ||
</I18nextProvider> | ||
</BrowserRouter> | ||
</MockedProvider>, | ||
); | ||
|
||
expect(screen.getByTestId('display-name')).toBeInTheDocument(); | ||
expect(screen.getByText('John Doe')).toBeInTheDocument(); | ||
expect(screen.getByText('User')).toBeInTheDocument(); | ||
expect(screen.getByTestId('display-type')).toBeInTheDocument(); | ||
expect(screen.getByAltText('profile picture')).toBeInTheDocument(); | ||
}); | ||
|
||
test('renders Super admin', () => { | ||
setItem('SuperAdmin', true); | ||
render( | ||
<MockedProvider mocks={MOCKS} addTypename={false}> | ||
<BrowserRouter> | ||
<ProfileCard /> | ||
</BrowserRouter> | ||
</MockedProvider>, | ||
); | ||
expect(screen.getByText('SuperAdmin')).toBeInTheDocument(); | ||
}); | ||
test('renders Admin', () => { | ||
setItem('AdminFor', ['123']); | ||
render( | ||
<MockedProvider mocks={MOCKS} addTypename={false}> | ||
<BrowserRouter> | ||
<ProfileCard /> | ||
</BrowserRouter> | ||
</MockedProvider>, | ||
); | ||
expect(screen.getByText('Admin')).toBeInTheDocument(); | ||
}); | ||
}); | ||
|
||
describe('Member screen routing testing', () => { | ||
test('navigates to /user/settings for a user', async () => { | ||
setItem('SuperAdmin', false); | ||
setItem('AdminFor', []); | ||
|
||
render( | ||
<MockedProvider mocks={MOCKS} addTypename={false}> | ||
<BrowserRouter> | ||
<I18nextProvider i18n={i18nForTest}> | ||
<ProfileCard /> | ||
</I18nextProvider> | ||
</BrowserRouter> | ||
</MockedProvider>, | ||
); | ||
|
||
await act(async () => { | ||
userEvent.click(screen.getByTestId('profileBtn')); | ||
}); | ||
|
||
expect(mockNavigate).toHaveBeenCalledWith('/user/settings'); | ||
}); | ||
|
||
test('navigates to /member/:orgId for non-user roles when orgId is not present', async () => { | ||
window.history.pushState({}, 'Test page', '/orglist'); | ||
setItem('SuperAdmin', true); // Set as admin | ||
setItem('id', '123'); | ||
|
||
render( | ||
<MockedProvider mocks={MOCKS} addTypename={false}> | ||
<BrowserRouter> | ||
<I18nextProvider i18n={i18nForTest}> | ||
<Routes> | ||
<Route path="/orglist" element={<ProfileCard />} /> | ||
</Routes> | ||
</I18nextProvider> | ||
</BrowserRouter> | ||
</MockedProvider>, | ||
); | ||
|
||
await act(async () => { | ||
userEvent.click(screen.getByTestId('profileBtn')); | ||
}); | ||
|
||
expect(mockNavigate).toHaveBeenCalledWith('/member/'); | ||
}); | ||
|
||
test('navigates to /member/:userID for non-user roles', async () => { | ||
window.history.pushState({}, 'Test page', '/321'); | ||
setItem('SuperAdmin', true); // Set as admin | ||
setItem('id', '123'); | ||
|
||
render( | ||
<MockedProvider mocks={MOCKS} addTypename={false}> | ||
<BrowserRouter> | ||
<I18nextProvider i18n={i18nForTest}> | ||
<Routes> | ||
<Route path="/:orgId" element={<ProfileCard />} /> | ||
</Routes> | ||
</I18nextProvider> | ||
</BrowserRouter> | ||
</MockedProvider>, | ||
); | ||
|
||
await act(async () => { | ||
userEvent.click(screen.getByTestId('profileBtn')); | ||
}); | ||
|
||
expect(mockNavigate).toHaveBeenCalledWith('/member/321'); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
import Avatar from 'components/Avatar/Avatar'; | ||
import React from 'react'; | ||
import { ButtonGroup, Dropdown } from 'react-bootstrap'; | ||
import { useNavigate, useParams } from 'react-router-dom'; | ||
import useLocalStorage from 'utils/useLocalstorage'; | ||
import styles from './../../style/app.module.css'; | ||
import ChevronRightIcon from '@mui/icons-material/ChevronRight'; | ||
|
||
/** | ||
* Renders a profile card for the user. | ||
* | ||
* This component displays the user's profile picture or an avatar, their name (truncated if necessary), | ||
* and their role (SuperAdmin, Admin, or User). It provides options to view the profile. | ||
* | ||
* - If a user image is available, it displays that; otherwise, it shows an avatar. | ||
* - The displayed name is truncated if it exceeds a specified length. | ||
* | ||
* @returns JSX.Element - The profile card . | ||
*/ | ||
const profileCard = (): JSX.Element => { | ||
const { getItem } = useLocalStorage(); | ||
const superAdmin = getItem('SuperAdmin'); | ||
const adminFor = getItem('AdminFor'); | ||
const userRole = superAdmin | ||
? 'SuperAdmin' | ||
: adminFor?.length > 0 | ||
? 'Admin' | ||
: 'User'; | ||
const firstName = getItem('FirstName'); | ||
const lastName = getItem('LastName'); | ||
const userImage = getItem('UserImage'); | ||
const navigate = useNavigate(); | ||
const { orgId } = useParams(); | ||
|
||
const MAX_NAME_LENGTH = 20; | ||
const fullName = `${firstName} ${lastName}`; | ||
const displayedName = | ||
fullName.length > MAX_NAME_LENGTH | ||
? fullName.substring(0, MAX_NAME_LENGTH - 3) + '...' | ||
: fullName; | ||
|
||
return ( | ||
<Dropdown as={ButtonGroup} variant="none"> | ||
<div className={styles.profileContainer}> | ||
<div className={styles.imageContainer}> | ||
{userImage && userImage !== 'null' ? ( | ||
<img | ||
src={userImage} | ||
alt={`profile picture`} | ||
data-testid="display-img" | ||
/> | ||
) : ( | ||
<Avatar | ||
data-testid="display-img" | ||
size={45} | ||
avatarStyle={styles.avatarStyle} | ||
name={`${firstName} ${lastName}`} | ||
alt={`dummy picture`} | ||
/> | ||
)} | ||
</div> | ||
<div className={styles.profileTextUserSidebarOrg}> | ||
<span className={styles.primaryText} data-testid="display-name"> | ||
{displayedName} | ||
</span> | ||
<span className={styles.secondaryText} data-testid="display-type"> | ||
{`${userRole}`} | ||
</span> | ||
</div> | ||
<button | ||
className="border-0 bg-white" | ||
data-testid="profileBtn" | ||
onClick={() => | ||
userRole === 'User' | ||
? navigate(`/user/settings`) | ||
: navigate(`/member/${orgId || ''}`) | ||
} | ||
> | ||
<ChevronRightIcon | ||
sx={{ | ||
color: 'gray', | ||
background: 'white', | ||
fontSize: 40, | ||
strokeWidth: 0.5, | ||
marginLeft: '50px', | ||
}} | ||
/> | ||
</button> | ||
</div> | ||
</Dropdown> | ||
); | ||
}; | ||
|
||
export default profileCard; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.