From affa1689bea6a827ca28c61ac85c3c74b2712ec8 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 1/2] 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 00000000..7bfb475c --- /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 13c899d6a626c8db9e1b070d8fc145edb878f36b Mon Sep 17 00:00:00 2001 From: Nikhil Trehan Date: Sun, 22 Sep 2024 20:11:18 -0400 Subject: [PATCH 2/2] 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 1424a375..5ff3ddac 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 d0c5506d..8d6c475f 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 1e5f72e9..929ec905 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 c540082f..6271a374 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 0d3759ed..adf81a32 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; }