From c76798f84db5c87f46914fd8ed397b3b8406fbff Mon Sep 17 00:00:00 2001 From: nora-zajzon Date: Tue, 17 Sep 2024 11:00:07 -0700 Subject: [PATCH 1/5] replaced html with mui --- client/src/components/admin/reports/index.jsx | 198 ++++++++---------- .../src/components/admin/reports/index.scss | 87 +++++--- 2 files changed, 148 insertions(+), 137 deletions(-) diff --git a/client/src/components/admin/reports/index.jsx b/client/src/components/admin/reports/index.jsx index 3e0baeea5..e05e83e7f 100644 --- a/client/src/components/admin/reports/index.jsx +++ b/client/src/components/admin/reports/index.jsx @@ -1,6 +1,7 @@ import React, {useState} from 'react'; import Loading from '../donutChartLoading'; import DatePicker from 'react-datepicker'; +import { Box, Button, Table, TableHead, TableRow, TableCell, TableBody, Typography } from '@mui/material'; import 'react-datepicker/dist/react-datepicker.css'; import '../../../common/datepicker/index.scss'; import './index.scss'; @@ -151,23 +152,19 @@ const LocationTableReport = ({eventTypeStats, hackNightTypeStats, handleFiltered } return ( -
+ {!isLoading ? ( -
- {isFilterButton && - - } + + )} {isDatepicker && -
-
-

Start

+ + + Start -
+ -
-

End

+ + End -
+ - -
+ + } -
-
- Stats calculated by: - {!isFiltered ? ( - all time - ) : ( - - {startTextDate} - - - {endTextDate} - - )} -
+ + + Stats calculated by: {!isFiltered ? 'all time' : `${startTextDate} - ${endTextDate}`} + -
All Events By Event Type
+ + All Events By Event Type + {isStatsByLocation ? ( - - - - {headerGroups.map(header => ( - - ))} - - - - - {dataForAllEventsReport.map((event) => ( - - - - - - - ))} - - {totalForAllEvents && - - - {totalForAllEvents.map((total, i) => ( - +
{header}
{event.location}{event.totalVolunteers}{event.totalVolunteerHours}{event.totalVolunteerAvgHours}
Total{total}
+ + + {headerGroups.map((header) => ( + {header} ))} - - } - -
- ) : ( -
No data for calculation stats
- )} - - -
HackNight Only
- {isStatsByHackNight ? ( - - - - {headerGroups.map(header => ( - + + + + {dataForAllEventsReport.map((event) => ( + + {event.location} + {event.totalVolunteers} + {event.totalVolunteerHours} + {event.totalVolunteerAvgHours} + ))} - - - - - {isStatsByHackNight && dataForHackNightReport.map((event) => ( - - - - - - - ))} - - {totalForHackNight && - - - {totalForHackNight.map((total, i) => ( - - ))} - - } - -
{header}
{event.location}{event.totalVolunteers}{event.totalVolunteerHours}{event.totalVolunteerAvgHours}
Total{total}
+ {totalForAllEvents && ( + + Total + {totalForAllEvents.map((total, i) => ( + {total} + ))} + + )} + + ) : ( -
No data for calculation stats
+ No data for calculation stats )} -
-
- ) : } -
+ + + HackNight Only + + {isStatsByHackNight ? ( + + + + {headerGroups.map((header) => ( + {header} + ))} + + + + {dataForHackNightReport.map((event) => ( + + {event.location} + {event.totalVolunteers} + {event.totalVolunteerHours} + {event.totalVolunteerAvgHours} + + ))} + {totalForHackNight && ( + + Total + {totalForHackNight.map((total, i) => ( + {total} + ))} + + )} + +
+ ) : ( + No data for calculation stats + )} + + + ) : ( + + )} + ); }; export default LocationTableReport; + \ No newline at end of file diff --git a/client/src/components/admin/reports/index.scss b/client/src/components/admin/reports/index.scss index 3d4a96c84..a10335500 100644 --- a/client/src/components/admin/reports/index.scss +++ b/client/src/components/admin/reports/index.scss @@ -1,35 +1,38 @@ -.admin-table-report{ +.admin-table-report { margin: 10px 0; font-size: 15px; text-align: center; + + .MuiTableCell-root { + font-size: 15px !important; + } } -.stats-section{ +.stats-section { margin-top: 10px; } -.table-header{ +.table-header { font-size: 15px; font-weight: bold; - background-color: #3d5a6c47; + background-color: transparent; margin: 20px 0 5px; padding: 5px; border-radius: 7px 7px 0 0; - &.m-t-small{ - margin-top: 10px; - } } -.admin-table{ +.admin-table { width: 100%; margin-top: 10px; border-collapse: collapse; - th, td{ + + th, td { text-align: center; height: 30px; } - tr:last-child{ - td{ + + tr:last-child { + td { color: #3D5A6C; font-weight: bold; border-top: 1px solid lightgray; @@ -37,34 +40,56 @@ } } -.filter-button{ - color: #3D5A6C; - border: 1px solid lightgray; - border-radius: 20px; - line-height: 1; - padding: 10px 20px; - margin: 0 auto; - transition: .3s ease; - max-width: 120px; - min-width: 120px; - height: auto; - font-family: 'Open Sans', sans-serif; - font-size: 15px; - &.calc-button{ - max-width: 150px; - min-width: 150px; +.filter-button { + color: #3D5A6C !important; + border: 1px solid lightgray !important; + border-radius: 20px !important; + line-height: 1 !important; + padding: 10px 20px !important; + margin: 0 auto !important; + transition: 0.3s ease !important; + max-width: 120px !important; + min-width: 120px !important; + height: auto !important; + font-family: 'Open Sans', sans-serif !important; + font-size: 15px !important; + + &.calc-button { + max-width: 150px !important; + min-width: 150px !important; } - &:hover{ - background-color: #3d5a6c47; + + &:hover { + background-color: #3d5a6c47 !important; } } -.dashboard-chart-container img{ + + + +.dashboard-chart-container img { max-width: 90px; } -.time-description{ +.time-description { font-size: 13px; text-align: right; margin-top: 10px; } + +.all-events-section, .hacknight-only-section { + margin-top: 10px; + background-color: #a2aab0; + padding: 10px; + border-radius: 7px; + font-weight: bold; +} + +.table-header { + background-color: #f5f5f5; +} + +.bold-text { + font-weight: bold !important; +} + From 5617e41e60f0ce84dd3e185b0d33da54f6bc530b Mon Sep 17 00:00:00 2001 From: Nikhil Trehan Date: Sun, 22 Sep 2024 20:11:18 -0400 Subject: [PATCH 2/5] Added User access level change code --- backend/models/user.model.js | 6 ++++- client/src/api/UserApiService.js | 17 ++++++++++++ .../src/components/user-admin/EditUsers.jsx | 26 +++++++++++++++---- client/src/pages/UserAdmin.jsx | 10 +++++++ client/src/sass/UserAdmin.scss | 6 ++--- 5 files changed, 56 insertions(+), 9 deletions(-) diff --git a/backend/models/user.model.js b/backend/models/user.model.js index 1424a3753..5ff3ddacd 100644 --- a/backend/models/user.model.js +++ b/backend/models/user.model.js @@ -9,7 +9,11 @@ const userSchema = mongoose.Schema({ lastName: { type: String }, }, email: { type: String, unique: true }, - accessLevel: { type: String, default: "user" }, + accessLevel: { + type: String, + enum: ["user", "admin"], // restricts values to "user" and "admin" + default: "user" + }, createdDate: { type: Date, default: Date.now }, currentRole: { type: String }, // will remove but need to update check-in form desiredRole: { type: String }, // will remove but need to update check-in form diff --git a/client/src/api/UserApiService.js b/client/src/api/UserApiService.js index d0c5506de..8d6c475f4 100644 --- a/client/src/api/UserApiService.js +++ b/client/src/api/UserApiService.js @@ -73,6 +73,23 @@ class UserApiService { alert('server not responding. Please try again.'); } } + + // Update user's access level (admin/user) + async updateUserAccessLevel(userToEdit, accessLevel) { + const url = `${this.baseUserUrl}${userToEdit._id}`; + const requestOptions = { + method: 'PATCH', + headers: this.headers, + body: JSON.stringify({ accessLevel }), + }; + + try { + return await fetch(url, requestOptions); + } catch (err) { + console.error('update access level error', err); + alert('server not responding. Please try again.'); + } + } } export default UserApiService; diff --git a/client/src/components/user-admin/EditUsers.jsx b/client/src/components/user-admin/EditUsers.jsx index 1e5f72e93..929ec9055 100644 --- a/client/src/components/user-admin/EditUsers.jsx +++ b/client/src/components/user-admin/EditUsers.jsx @@ -3,10 +3,11 @@ import '../../sass/UserAdmin.scss'; import { FormGroup, FormControlLabel, Switch } from '@mui/material' // child of UserAdmin. Displays form to update users. -const EditUsers = ({ userToEdit, backToSearch, updateUserDb, projects, updateUserActiveStatus }) => { +const EditUsers = ({ userToEdit, backToSearch, updateUserDb, projects, updateUserActiveStatus, updateUserAccessLevel }) => { const [userManagedProjects, setUserManagedProjects] = useState([]); // The projects that the selected user is assigned const [projectValue, setProjectValue] = useState(''); // State and handler for form in EditUsers const [isActive, setIsActive] = useState(userToEdit.isActive); + const [isAdmin, setIsAdmin] = useState(userToEdit.accessLevel === "admin"); // Prepare data for display const userName = `${userToEdit.name?.firstName} ${userToEdit.name?.lastName}`; @@ -64,6 +65,12 @@ const EditUsers = ({ userToEdit, backToSearch, updateUserDb, projects, updateUse updateUserActiveStatus(userToEdit, !isActive) } + const handleSetAccessLevel = () => { + const newAccessLevel = isAdmin ? "user" : "admin"; + setIsAdmin(!isAdmin); + updateUserAccessLevel(userToEdit, newAccessLevel); + }; + return (
@@ -74,15 +81,24 @@ const EditUsers = ({ userToEdit, backToSearch, updateUserDb, projects, updateUse
Email:
{userEmail}
-
-
Is Active:
-
- {isActive.toString()} +
+
Is Active:
+
+ {isActive.toString()} } onClick={() => handleSetIsActive()} />
+
+
VRSM Admin:
+
+ {isAdmin ? "Yes" : "No"} + + } onClick={() => handleSetAccessLevel()} /> + +
+
Projects:
diff --git a/client/src/pages/UserAdmin.jsx b/client/src/pages/UserAdmin.jsx index c540082ff..6271a374d 100644 --- a/client/src/pages/UserAdmin.jsx +++ b/client/src/pages/UserAdmin.jsx @@ -37,6 +37,15 @@ const UserAdmin = () => { }, [userApiService, fetchUsers] ) + // Update user's access level (admin/user) + const updateUserAccessLevel = useCallback( + async (user, newAccessLevel) => { + await userApiService.updateUserAccessLevel(user, newAccessLevel); + fetchUsers(); + }, + [userApiService, fetchUsers] + ); + const fetchProjects = useCallback(async () => { const projectRes = await projectApiService.fetchProjects(); setProjects(projectRes); @@ -65,6 +74,7 @@ const UserAdmin = () => { updateUserDb={updateUserDb} backToSearch={backToSearch} updateUserActiveStatus={updateUserActiveStatus} + updateUserAccessLevel={updateUserAccessLevel} /> ); } diff --git a/client/src/sass/UserAdmin.scss b/client/src/sass/UserAdmin.scss index 0d3759edb..adf81a32e 100644 --- a/client/src/sass/UserAdmin.scss +++ b/client/src/sass/UserAdmin.scss @@ -65,18 +65,18 @@ margin-bottom: 8px; } -.user-is-active-column-left { +.user-toggle-column-left { display: flex; flex-direction: column; flex-basis: 15%; } -.active-status { +.toggle-status { margin-right: 15px; width: 25px; } -.is-active-flex { +.toggle-flex { display: flex; align-items: center; } From 96ae0b3e020191fa84389438a5c0fe73382a5bf7 Mon Sep 17 00:00:00 2001 From: Mudassir Hussain Date: Wed, 18 Sep 2024 23:05:28 -0400 Subject: [PATCH 3/5] Removed .github/workflows/New-issue-create-card.yml from the project --- .github/workflows/New-issue-create-card.yml | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 .github/workflows/New-issue-create-card.yml diff --git a/.github/workflows/New-issue-create-card.yml b/.github/workflows/New-issue-create-card.yml deleted file mode 100644 index d64361822..000000000 --- a/.github/workflows/New-issue-create-card.yml +++ /dev/null @@ -1,13 +0,0 @@ -name: Create card for new issues -on: - issues: - types: [opened] -jobs: - createCard: - runs-on: ubuntu-latest - steps: - - name: Create or Update Project Card - uses: peter-evans/create-or-update-project-card@v2 - with: - project-name: VRMS - Active Project Board - column-name: New Issue Approval From 609f4de130efb5563a012b4b40ba206070da2fce Mon Sep 17 00:00:00 2001 From: Jack Haeger <134463646+JackHaeg@users.noreply.github.com> Date: Mon, 26 Aug 2024 14:47:10 -0700 Subject: [PATCH 4/5] Create CODE_OF_CONDUCT.md - Created Code of Conduct file per instructions within #655 --- CODE_OF_CONDUCT.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 CODE_OF_CONDUCT.md diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 000000000..7bfb475c1 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1 @@ +VRMS is governed by the [Hack for LA Code of Conduct](https://www.hackforla.org/code-of-conduct/) which applies to any interaction on our VRMS slack channel (inside the HackforLA Slack workspace), direct slack messages, github org or repository, or any other communication medium. From fd060f4250a04b5943a179fb5c04bd200d854b65 Mon Sep 17 00:00:00 2001 From: nora-zajzon Date: Tue, 24 Sep 2024 08:47:12 -0700 Subject: [PATCH 5/5] using inline styling now --- client/src/components/admin/reports/index.jsx | 139 ++++++++++++++---- .../src/components/admin/reports/index.scss | 89 ++++------- 2 files changed, 142 insertions(+), 86 deletions(-) diff --git a/client/src/components/admin/reports/index.jsx b/client/src/components/admin/reports/index.jsx index e05e83e7f..7c1242f54 100644 --- a/client/src/components/admin/reports/index.jsx +++ b/client/src/components/admin/reports/index.jsx @@ -27,6 +27,87 @@ const LocationTableReport = ({eventTypeStats, hackNightTypeStats, handleFiltered const [startTextDate, setStartTextDate] = useState(new Date().toLocaleDateString("en-US")); const [endTextDate, setEndTextDate] = useState(new Date().toLocaleDateString("en-US")); + const styles = { + adminTableReport: { + margin: '10px 0', + fontSize: '15px', + textAlign: 'center', + }, + statsSection: { + marginTop: '10px', + textAlign: 'right' + }, + tableHeader: { + fontSize: '15px', + fontWeight: 'bold', + backgroundColor: '#3d5a6c47', + margin: '20px 0 5px', + padding: '5px', + borderRadius: '7px 7px 0 0', + textAlign: 'center' + }, + adminTable: { + width: '100%', + marginTop: '10px', + borderCollapse: 'collapse', + border: 'none', + }, + tableCell: { + textAlign: 'center', + height: '30px', + border: 'none', + }, + lastRowCell: { + color: '#3D5A6C', + fontWeight: 'bold', + borderTop: '1px solid lightgray', + borderBottom: 'none', + textAlign: 'center', + height: '30px', + + }, + firstRowCell: { + color: '#3D5A6C', + fontWeight: 'bold', + borderBottom: 'none', + textAlign: 'center', + height: '30px', + + }, + filterButton: { + color: '#3D5A6C', + border: '1px solid lightgray', + borderRadius: '20px', + lineHeight: '1', + padding: '10px 20px', + margin: '0 auto', + transition: '.3s ease', + maxWidth: '120px', + minWidth: '120px', + height: 'auto', + fontFamily: "'Open Sans', sans-serif", + fontSize: '15px', + }, + calcButton: { + maxWidth: '150px', + minWidth: '150px', + }, + chartImage: { + maxWidth: '90px', + }, + timeDescription: { + fontSize: '13px', + textAlign: 'right', + marginTop: '10px', + }, + boldText: { + fontWeight: 'bold', + fontSize: '18px', + color: '#3D5A6C', + }, + + }; + prepareDataForReport( eventTypeStats, eventTypes, @@ -154,17 +235,17 @@ const LocationTableReport = ({eventTypeStats, hackNightTypeStats, handleFiltered return ( {!isLoading ? ( - + {isFilterButton && ( - )} {isDatepicker && - - - Start + + + Start - - End + + End - } - + Stats calculated by: {!isFiltered ? 'all time' : `${startTextDate} - ${endTextDate}`} - - All Events By Event Type + + All Events By Event Type {isStatsByLocation ? ( - +
{headerGroups.map((header) => ( - {header} + {header} ))} {dataForAllEventsReport.map((event) => ( - {event.location} - {event.totalVolunteers} - {event.totalVolunteerHours} - {event.totalVolunteerAvgHours} + {event.location} + {event.totalVolunteers} + {event.totalVolunteerHours} + {event.totalVolunteerAvgHours} ))} {totalForAllEvents && ( - Total + Total {totalForAllEvents.map((total, i) => ( - {total} + {total} ))} )} @@ -235,32 +316,32 @@ const LocationTableReport = ({eventTypeStats, hackNightTypeStats, handleFiltered No data for calculation stats )} - - HackNight Only + + HackNight Only {isStatsByHackNight ? ( -
+
{headerGroups.map((header) => ( - {header} + {header} ))} {dataForHackNightReport.map((event) => ( - {event.location} - {event.totalVolunteers} - {event.totalVolunteerHours} - {event.totalVolunteerAvgHours} + {event.location} + {event.totalVolunteers} + {event.totalVolunteerHours} + {event.totalVolunteerAvgHours} ))} {totalForHackNight && ( - Total + Total {totalForHackNight.map((total, i) => ( - {total} + {total} ))} )} diff --git a/client/src/components/admin/reports/index.scss b/client/src/components/admin/reports/index.scss index a10335500..be64321c2 100644 --- a/client/src/components/admin/reports/index.scss +++ b/client/src/components/admin/reports/index.scss @@ -1,38 +1,35 @@ -.admin-table-report { +.admin-table-report{ margin: 10px 0; font-size: 15px; text-align: center; - - .MuiTableCell-root { - font-size: 15px !important; - } } -.stats-section { +.stats-section{ margin-top: 10px; } -.table-header { +.table-header{ font-size: 15px; font-weight: bold; - background-color: transparent; + background-color: #3d5a6c47; margin: 20px 0 5px; padding: 5px; border-radius: 7px 7px 0 0; + &.m-t-small{ + margin-top: 10px; + } } -.admin-table { +.admin-table{ width: 100%; margin-top: 10px; border-collapse: collapse; - - th, td { + th, td{ text-align: center; height: 30px; } - - tr:last-child { - td { + tr:last-child{ + td{ color: #3D5A6C; font-weight: bold; border-top: 1px solid lightgray; @@ -40,56 +37,34 @@ } } -.filter-button { - color: #3D5A6C !important; - border: 1px solid lightgray !important; - border-radius: 20px !important; - line-height: 1 !important; - padding: 10px 20px !important; - margin: 0 auto !important; - transition: 0.3s ease !important; - max-width: 120px !important; - min-width: 120px !important; - height: auto !important; - font-family: 'Open Sans', sans-serif !important; - font-size: 15px !important; - - &.calc-button { - max-width: 150px !important; - min-width: 150px !important; +.filter-button{ + color: #3D5A6C; + border: 1px solid lightgray; + border-radius: 20px; + line-height: 1; + padding: 10px 20px; + margin: 0 auto; + transition: .3s ease; + max-width: 120px; + min-width: 120px; + height: auto; + font-family: 'Open Sans', sans-serif; + font-size: 15px; + &.calc-button{ + max-width: 150px; + min-width: 150px; } - - &:hover { - background-color: #3d5a6c47 !important; + &:hover{ + background-color: #3d5a6c47; } } - - - -.dashboard-chart-container img { +.dashboard-chart-container img{ max-width: 90px; } -.time-description { +.time-description{ font-size: 13px; text-align: right; margin-top: 10px; -} - -.all-events-section, .hacknight-only-section { - margin-top: 10px; - background-color: #a2aab0; - padding: 10px; - border-radius: 7px; - font-weight: bold; -} - -.table-header { - background-color: #f5f5f5; -} - -.bold-text { - font-weight: bold !important; -} - +} \ No newline at end of file