Skip to content
Open
Changes from all 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
65 changes: 58 additions & 7 deletions client/src/components/user-admin/UserPermissionSearch.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState, useEffect } from 'react';
import { useState, useEffect } from 'react';
import {
Box,
Button,
Expand Down Expand Up @@ -101,7 +101,7 @@ const DummyComponent = ({ data, isProjectLead, setUserToEdit }) => {
};

const UserPermissionSearch = ({ admins, projectLeads, setUserToEdit }) => {
const [userType, setUserType] = useState('admin'); // Which results will display
const [userType] = useState('admin'); // Which results will display
const [searchText, setSearchText] = useState(''); // Search term for the admin/PM search
const [isProjectLead, setIsProjectLead] = useState(false);

Expand Down Expand Up @@ -136,15 +136,15 @@ const UserPermissionSearch = ({ admins, projectLeads, setUserToEdit }) => {
.filter((user) =>
isProjectLead
? user.isProjectLead === true
: user.isProjectLead === undefined
: user.isProjectLead === undefined,
)
.flatMap((user) =>
isProjectLead && user.managedProjectNames.length > 0
? user.managedProjectNames.map((managedProjectName) => ({
...user,
managedProjectName,
}))
: [{ ...user }]
: [{ ...user }],
)
.filter((user) => {
const fullName =
Expand Down Expand Up @@ -175,13 +175,13 @@ const UserPermissionSearch = ({ admins, projectLeads, setUserToEdit }) => {
filteredData = resultData.filter((user) =>
isProjectLead
? user.isProjectLead === true
: user.isProjectLead === undefined
: user.isProjectLead === undefined,
);

if (!isProjectLead) {
// Default display for admins, sorted ASC based on first name
filteredData.sort((u1, u2) =>
u1.name?.firstName.localeCompare(u2.name?.firstName)
u1.name?.firstName.localeCompare(u2.name?.firstName),
);
} else {
// Default display of all PMs, sorted ASC based on project name, then first name
Expand All @@ -194,7 +194,7 @@ const UserPermissionSearch = ({ admins, projectLeads, setUserToEdit }) => {
tempFilter.sort(
(u1, u2) =>
u1.managedProjectName.localeCompare(u2.managedProjectName) ||
u1.name?.firstName.localeCompare(u2.name?.firstName)
u1.name?.firstName.localeCompare(u2.name?.firstName),
);
filteredData = [...tempFilter];
}
Expand All @@ -203,6 +203,42 @@ const UserPermissionSearch = ({ admins, projectLeads, setUserToEdit }) => {
filteredData = getFilteredData(resultData, searchText, isProjectLead);
}

// No need to limit export to the search results
const exportAllData = getFilteredData(resultData, '', isProjectLead);

// Export CSV file
const exportCSV = (data, fileName) => {
// Header row
const headers = ['User Name', 'Project Name'];

// Map each user into CSV row values
const dataItems = data.map((user) => [
`${user.name?.firstName ?? ''} ${user.name?.lastName ?? ''}`,
user.managedProjectName ?? '',
]);

// Combine header + data rows
const rows = [headers, ...dataItems];

// Convert rows to CSV formatted string
const csvData = rows.map((row) => row.join(',')).join('\r\n');

// Create CSV Blob from string
const blob = new Blob([csvData], { type: 'text/csv' });
const url = URL.createObjectURL(blob);

// Create a temporary download link
const link = document.createElement('a');
link.href = url;
link.download = fileName;

// Trigger download
link.click();

// Clean up object URL
URL.revokeObjectURL(url);
};

return (
<Box className="container--usermanagement" sx={{ px: '1.8rem', mb: 0 }}>
<Box
Expand Down Expand Up @@ -250,6 +286,21 @@ const UserPermissionSearch = ({ admins, projectLeads, setUserToEdit }) => {
</Button>
</ButtonGroup>
</Box>
{isProjectLead && (
<Box
sx={{
mb: 2,
}}
>
<Button
sx={Buttonsx}
variant="secondary"
onClick={() => exportCSV(exportAllData, 'project_members.csv')}
>
Export CSV
</Button>
</Box>
)}
<TextField
type="text"
placeholder={isProjectLead ? 'Search name or project' : 'Search name'}
Expand Down
Loading