Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented correct user roles Fixes #3106 #3111

Merged
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 26 additions & 17 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,24 +30,29 @@ import CommunityProfile from 'screens/CommunityProfile/CommunityProfile';
import OrganizationVenues from 'screens/OrganizationVenues/OrganizationVenues';
import Leaderboard from 'screens/Leaderboard/Leaderboard';

import React from 'react';
import React, { useEffect } from 'react';
// User Portal Components
import Donate from 'screens/UserPortal/Donate/Donate';
import Events from 'screens/UserPortal/Events/Events';
import Posts from 'screens/UserPortal/Posts/Posts';
import Organizations from 'screens/UserPortal/Organizations/Organizations';
import People from 'screens/UserPortal/People/People';
import Settings from 'screens/UserPortal/Settings/Settings';
import Chat from 'screens/UserPortal/Chat/Chat';
// import Chat from 'screens/UserPortal/Chat/Chat';
import { useQuery } from '@apollo/client';
import { CHECK_AUTH } from 'GraphQl/Queries/Queries';
import Advertisements from 'components/Advertisements/Advertisements';
import SecuredRouteForUser from 'components/UserPortal/SecuredRouteForUser/SecuredRouteForUser';

import useLocalStorage from 'utils/useLocalstorage';
raggettii marked this conversation as resolved.
Show resolved Hide resolved
import UserScreen from 'screens/UserPortal/UserScreen/UserScreen';
import EventDashboardScreen from 'components/EventDashboardScreen/EventDashboardScreen';
import Campaigns from 'screens/UserPortal/Campaigns/Campaigns';
import Pledges from 'screens/UserPortal/Pledges/Pledges';
import VolunteerManagement from 'screens/UserPortal/Volunteer/VolunteerManagement';
import LeaveOrganization from 'screens/UserPortal/LeaveOrganization/LeaveOrganization';

// const { setItem } = useLocalStorage();
const { setItem } = useLocalStorage();

/**
* This is the main function for our application. It sets up all the routes and components,
Expand Down Expand Up @@ -92,20 +97,20 @@ function app(): JSX.Element {

// TODO: Fetch Installed plugin extras and store for use within MainContent and Side Panel Components.

// const { data, loading } = useQuery(CHECK_AUTH);
const { data, loading } = useQuery(CHECK_AUTH);
raggettii marked this conversation as resolved.
Show resolved Hide resolved

// useEffect(() => {
// if (data) {
// setItem('name', `${data.checkAuth.firstName} ${data.checkAuth.lastName}`);
// setItem('id', data.checkAuth._id);
// setItem('email', data.checkAuth.email);
// setItem('IsLoggedIn', 'TRUE');
// setItem('FirstName', data.checkAuth.firstName);
// setItem('LastName', data.checkAuth.lastName);
// setItem('UserImage', data.checkAuth.image);
// setItem('Email', data.checkAuth.email);
// }
// }, [data, loading]);
useEffect(() => {
if (data) {
setItem('name', `${data.checkAuth.firstName} ${data.checkAuth.lastName}`);
setItem('id', data.checkAuth._id);
setItem('email', data.checkAuth.email);
setItem('IsLoggedIn', 'TRUE');
setItem('FirstName', data.checkAuth.firstName);
setItem('LastName', data.checkAuth.lastName);
setItem('UserImage', data.checkAuth.image);
setItem('Email', data.checkAuth.email);
}
}, [data, loading]);
coderabbitai[bot] marked this conversation as resolved.
Show resolved Hide resolved

const extraRoutes = Object.entries(installedPlugins).map(
(
Expand Down Expand Up @@ -192,9 +197,12 @@ function app(): JSX.Element {
<Route path="/user/people/:orgId" element={<People />} />
<Route path="/user/donate/:orgId" element={<Donate />} />
<Route path="/user/events/:orgId" element={<Events />} />
<Route path="/user/chat/:orgId" element={<Chat />} />
<Route path="/user/campaigns/:orgId" element={<Campaigns />} />
<Route path="/user/pledges/:orgId" element={<Pledges />} />
<Route
path="/user/leaveOrg/:orgId"
element={<LeaveOrganization />}
/>
<Route
path="/user/volunteer/:orgId"
element={<VolunteerManagement />}
Expand All @@ -207,6 +215,7 @@ function app(): JSX.Element {
</Route>
</Route>
</Route>
{/* <SecuredRouteForUser path="/user/chat" component={Chat} /> */}
<Route path="*" element={<PageNotFound />} />
</Routes>
</>
Expand Down
58 changes: 1 addition & 57 deletions src/screens/UserPortal/People/People.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { Provider } from 'react-redux';
import { store } from 'state/store';
import i18nForTest from 'utils/i18nForTest';
import { StaticMockLink } from 'utils/StaticMockLink';
import type { InterfaceMember } from './People';
// import type { InterfaceMember } from './People';
import People from './People';
import userEvent from '@testing-library/user-event';
import { vi } from 'vitest';
Expand Down Expand Up @@ -168,62 +168,6 @@ describe('Testing People Screen [User Portal]', () => {
expect(screen.queryAllByText('Noble Mittal')).not.toBe([]);
});

function compareProperties(
expectedProps: string[],
actualObject: object,
): boolean {
const actualProps = Object.keys(actualObject);
return expectedProps.every((prop) => actualProps.includes(prop));
}

describe('InterfaceMember properties comparison', () => {
it('should have all required properties', () => {
const expectedProperties = [
'firstName',
'lastName',
'image',
'_id',
'email',
'__typename',
];

const mockValidData: InterfaceMember = {
firstName: 'John',
lastName: 'Doe',
image: 'https://example.com/john.jpg',
_id: '1',
email: 'john.doe@example.com',
__typename: 'User',
};

const result = compareProperties(expectedProperties, mockValidData);
expect(result).toBe(true);
});

it('should fail if __typename is replaced with username', () => {
const expectedProperties = [
'firstName',
'lastName',
'image',
'_id',
'email',
'__typename', // Expect this property
];

const mockInvalidData = {
firstName: 'John',
lastName: 'Doe',
image: 'https://example.com/john.jpg',
_id: '1',
email: 'john.doe@example.com',
username: 'Member', // Incorrect property
};

const result = compareProperties(expectedProperties, mockInvalidData);
expect(result).toBe(false);
});
});

it('Search works properly by pressing enter', async () => {
render(
<MockedProvider addTypename={false} link={link}>
Expand Down
78 changes: 41 additions & 37 deletions src/screens/UserPortal/People/People.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@
sno: string;
}

export interface InterfaceMember {
interface InterfaceMember {
firstName: string;
lastName: string;
image: string;
_id: string;
email: string;
__typename: string;
userType: string;
}

/**
Expand All @@ -37,20 +37,19 @@
* and paginate through the list.
*/
export default function people(): JSX.Element {
// i18n translation hook for user organization related translations
const { t } = useTranslation('translation', {
keyPrefix: 'people',
});

// i18n translation hook for common translations
const { t: tCommon } = useTranslation('common');

// State for managing current page in pagination
const [page, setPage] = useState<number>(0);

// State for managing the number of rows per page in pagination
const [rowsPerPage, setRowsPerPage] = useState<number>(5);
const [members, setMembers] = useState([]);
const [members, setMembers] = useState<InterfaceMember[]>([]);
const [allMembers, setAllMembers] = useState<InterfaceMember[]>([]);
const [admins, setAdmins] = useState<InterfaceMember[]>([]);
const [mode, setMode] = useState<number>(0);

// Extracting organization ID from URL parameters
Expand All @@ -69,29 +68,18 @@
},
},
);

// Query to fetch list of admins of the organization
const { data: data2 } = useQuery(ORGANIZATION_ADMINS_LIST, {
variables: { id: organizationId },
});

/**
* Handles page change in pagination.
*
*/
/* istanbul ignore next */
const handleChangePage = (
_event: React.MouseEvent<HTMLButtonElement> | null,
newPage: number,
): void => {
setPage(newPage);
};

/**
* Handles change in the number of rows per page.
*
*/
/* istanbul ignore next */
const handleChangeRowsPerPage = (
event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
): void => {
Expand All @@ -101,20 +89,12 @@
setPage(0);
};

/**
* Searches for members based on the filter value.
*
*/
const handleSearch = (newFilter: string): void => {
refetch({
firstName_contains: newFilter,
});
};

/**
* Handles search operation triggered by pressing the Enter key.
*
*/
const handleSearchByEnter = (
e: React.KeyboardEvent<HTMLInputElement>,
): void => {
Expand All @@ -124,34 +104,58 @@
}
};

/**
* Handles search operation triggered by clicking the search button.
*/
const handleSearchByBtnClick = (): void => {
const inputValue =
(document.getElementById('searchPeople') as HTMLInputElement)?.value ||
'';
handleSearch(inputValue);
};

useEffect(() => {
if (data2) {
const admin = data2.organizations[0].admins[0];
const updatedAdmin: InterfaceMember = {
...admin,
userType: 'Admin',
};
setAdmins([updatedAdmin]);
}
}, [data2]);

useEffect(() => {
if (data) {
setMembers(data.organizationsMemberConnection.edges);
const updatedAdmins = data.organizationsMemberConnection.edges.map(
(memberData: InterfaceMember) => ({
...memberData, // Spread the existing properties
userType: admins?.some((admin) => admin._id === memberData._id)
? 'Admin'
: 'Member',
}),
);

setAllMembers(updatedAdmins);
setMembers(updatedAdmins);
}
}, [data]);
}, [data, admins]);

/**
* Updates the list of members based on the selected filter mode.
*/
/* istanbul ignore next */
if (admins && admins.length > 0) {
const adminIds = admins.map((adm) => adm._id);
for (let i = 0; i < allMembers.length; i++) {
if (adminIds.includes(allMembers[i]._id)) {
allMembers[i].userType = 'Admin';
} else {
allMembers[i].userType = 'Member';
}
}
}
coderabbitai[bot] marked this conversation as resolved.
Show resolved Hide resolved
useEffect(() => {
if (mode == 0) {
if (data) {
setMembers(data.organizationsMemberConnection.edges);
setMembers(allMembers);

Check warning on line 154 in src/screens/UserPortal/People/People.tsx

View check run for this annotation

Codecov / codecov/patch

src/screens/UserPortal/People/People.tsx#L154

Added line #L154 was not covered by tests
}
} else if (mode == 1) {
if (data2) {
setMembers(data2.organizations[0].admins);
setMembers(admins);
}
}
}, [mode]);
Expand Down Expand Up @@ -243,7 +247,7 @@
image: member.image,
id: member._id,
email: member.email,
role: member.__typename,
role: member.userType,
sno: (index + 1).toString(),
};
return <PeopleCard key={index} {...cardProps} />;
Expand Down
Loading