Skip to content

Commit

Permalink
feat(UI): added manage group-users page
Browse files Browse the repository at this point in the history
Signed-off-by: dushimsam <[email protected]>
  • Loading branch information
dushimsam committed Sep 1, 2022
1 parent 615a373 commit 4216de9
Show file tree
Hide file tree
Showing 11 changed files with 445 additions and 3 deletions.
6 changes: 6 additions & 0 deletions src/Routes.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ const UploadDelete = React.lazy(() => import("pages/Organize/Uploads/Delete"));
const GroupCreate = React.lazy(() => import("pages/Admin/Group/Create"));
const DeleteGroup = React.lazy(() => import("pages/Admin/Group/Delete"));
const DeleteUser = React.lazy(() => import("pages/Admin/Users/Delete"));
const ManageGroup = React.lazy(() => import("pages/Admin/Group/Manage"));
const AddUser = React.lazy(() => import("pages/Admin/Users/Add"));
const EditUser = React.lazy(() => import("pages/Admin/Users/Edit"));
const AddLicense = React.lazy(() => import("pages/Admin/License/Create"));
Expand Down Expand Up @@ -287,6 +288,11 @@ const Routes = () => {
path={routes.admin.group.create}
component={GroupCreate}
/>
<AdminLayout
exact
path={routes.admin.group.manageGroup}
component={ManageGroup}
/>
<AdminLayout
exact
path={routes.admin.group.delete}
Expand Down
38 changes: 38 additions & 0 deletions src/api/groups.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,29 @@ export const createGroupApi = (name) => {
});
};

// Get all group members
export const getAllGroupMembersApi = (groupId) => {
const url = endpoints.admin.groups.getAllGroupMembers(groupId);
return sendRequest({
url,
method: "GET",
headers: {
Authorization: getToken(),
},
});
};

// Remove Group Member
export const removeGroupMemberApi = (groupId, userId) => {
const url = endpoints.admin.groups.removeGroupMember(groupId, userId);
return sendRequest({
url,
method: "DELETE",
headers: {
Authorization: getToken(),
},
});
};
// Delete a group
export const deleteGroupApi = (id) => {
const url = endpoints.admin.groups.delete(id);
Expand All @@ -73,6 +96,21 @@ export const deleteGroupApi = (id) => {
headers: {
Authorization: getToken(),
},
});
};

// Change user permission
export const changeUserPermissionApi = (groupId, userId, permission) => {
const url = endpoints.admin.groups.changeUserPermission(groupId, userId);
return sendRequest({
url,
method: "PUT",
headers: {
Authorization: getToken(),
},
body: {
perm: permission,
},
addGroupName: false,
});
};
67 changes: 66 additions & 1 deletion src/api/groups.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,13 @@

import sendRequest from "api/sendRequest";
import endpoints from "constants/endpoints";
import { createGroupApi, getAllGroupsApi } from "api/groups";
import {
changeUserPermissionApi,
createGroupApi,
getAllGroupMembersApi,
getAllGroupsApi,
removeGroupMemberApi,
} from "api/groups";
import { getToken } from "shared/authHelper";

jest.mock("api/sendRequest");
Expand Down Expand Up @@ -56,4 +62,63 @@ describe("groups", () => {
})
);
});

test("removeGroupMemberApi", () => {
const groupId = 2;
const userId = 1;
const url = endpoints.admin.groups.removeGroupMember(groupId, userId);
sendRequest.mockImplementation(() => true);

expect(removeGroupMemberApi(groupId, userId)).toBe(sendRequest({}));
expect(sendRequest).toHaveBeenCalledWith(
expect.objectContaining({
url,
method: "DELETE",
headers: {
Authorization: getToken(),
},
})
);
});

test("getAllGroupMembersApi", () => {
const groupId = 1;
const url = endpoints.admin.groups.getAllGroupMembers(groupId);
sendRequest.mockImplementation(() => true);

expect(getAllGroupMembersApi(groupId)).toBe(sendRequest({}));
expect(sendRequest).toHaveBeenCalledWith(
expect.objectContaining({
url,
method: "GET",
headers: {
Authorization: getToken(),
},
})
);
});

test("changeUserPermissionApi", () => {
const groupId = 1;
const userId = 1;
const permission = 2;
const url = endpoints.admin.groups.changeUserPermission(groupId, userId);
sendRequest.mockImplementation(() => true);

expect(changeUserPermissionApi(groupId, userId, permission)).toBe(
sendRequest({})
);
expect(sendRequest).toHaveBeenCalledWith(
expect.objectContaining({
url,
method: "PUT",
headers: {
Authorization: getToken(),
},
body: {
perm: permission,
},
})
);
});
});
103 changes: 103 additions & 0 deletions src/components/Admin/ChangePermission.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/*
Copyright (C) 2022 Samuel Dushimimana ([email protected])
SPDX-License-Identifier: GPL-2.0
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

import React, { useEffect, useState } from "react";

import { InputContainer } from "components/Widgets";

// Required functions for calling APIs
import { changeUserPermission, removeGroupMember } from "services/groups";

import PropTypes from "prop-types";

// Required constants
import { userPermissions } from "constants/constants";

const ChangePermissionContainer = ({
perm,
setShowMessage,
setMessage,
currGroup,
user,
handleFetchGroupMembers,
}) => {
const [selectedPerm, setSelectedPerm] = useState(perm);

useEffect(() => {
setSelectedPerm(perm);
}, [perm]);

const handleSetNewPermission = async (newPerm) => {
setSelectedPerm(newPerm);
// eslint-disable-next-line no-console
try {
let res;
if (parseInt(newPerm, 10) === -1) {
// eslint-disable-next-line no-console
console.log(`HERE ID ${newPerm}`);
res = await removeGroupMember(currGroup, user.id);
} else {
res = await changeUserPermission(currGroup, user.id, newPerm);
}

setShowMessage(true);
setMessage({
type: "success",
text: res.message,
});

handleFetchGroupMembers(currGroup);
} catch (e) {
setMessage({
type: "danger",
text: e.message,
});
} finally {
setTimeout(() => {
setShowMessage(false);
}, [3000]);
}
};
return (
<tr>
<td>{user.name}</td>
<td>
<InputContainer
type="select"
name="name"
options={userPermissions}
id="select-tag"
value={selectedPerm}
property="name"
onChange={(e) => handleSetNewPermission(e.target.value)}
/>
</td>
</tr>
);
};

ChangePermissionContainer.propTypes = {
perm: PropTypes.number,
setMessage: PropTypes.func,
currGroup: PropTypes.number,
user: PropTypes.node,
handleFetchGroupMembers: PropTypes.func,
setShowMessage: PropTypes.func,
};

export default ChangePermissionContainer;
4 changes: 2 additions & 2 deletions src/components/Header/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -258,9 +258,9 @@ const Header = () => {
</NavDropdown.Item>
<NavDropdown.Item
as={Link}
to={routes.admin.group.delete}
to={routes.admin.group.manageGroup}
>
Delete Group
Manage Group Users
</NavDropdown.Item>
</div>
</DropdownButton>
Expand Down
3 changes: 3 additions & 0 deletions src/components/Widgets/Input/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const InputContainer = ({
id,
className,
onChange,
defaultValue = null,
children,
checked = false,
placeholder = null,
Expand Down Expand Up @@ -70,6 +71,7 @@ const InputContainer = ({
className ? `mr-2 form-control ${className}` : `mr-2 form-control`
}
value={value}
defaultValue={defaultValue}
onChange={onChange}
multiple={multiple && multiple}
size={multiple ? "15" : ""}
Expand Down Expand Up @@ -125,6 +127,7 @@ InputContainer.propTypes = {
onChange: PropTypes.func,
checked: PropTypes.bool,
disabled: PropTypes.bool,
defaultValue: PropTypes.string,
children: PropTypes.node,
options: PropTypes.arrayOf(
PropTypes.shape({
Expand Down
20 changes: 20 additions & 0 deletions src/constants/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -356,3 +356,23 @@ export const agents = {
reso: "REUSE.Software Analysis (forces *Ojo License Analysis*)",
heritage: "Software Heritage Analysis",
};

// eslint-disable-next-line camelcase
export const userPermissions = [
{
id: -1,
name: "None",
},
{
id: 0,
name: "User",
},
{
id: 1,
name: "Admin",
},
{
id: 2,
name: "Advisor",
},
];
5 changes: 5 additions & 0 deletions src/constants/endpoints.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ const endpoints = {
getAll: () => `${apiUrl}/groups`,
getAllDeletable: () => `${apiUrl}/groups/deletable`,
delete: (groupId) => `${apiUrl}/groups/${groupId}`,
getAllGroupMembers: (groupId) => `${apiUrl}/groups/${groupId}/members`,
changeUserPermission: (groupId, userId) =>
`${apiUrl}/groups/${groupId}/user/${userId}`,
removeGroupMember: (groupId, userId) =>
`${apiUrl}/groups/${groupId}/user/${userId}`,
},
},
license: {
Expand Down
1 change: 1 addition & 0 deletions src/constants/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ const routes = {
group: {
create: "/admin/group/create",
delete: "/admin/group/delete",
manageGroup: "/admin/group/manage",
},
users: {
add: "/admin/users/add",
Expand Down
Loading

0 comments on commit 4216de9

Please sign in to comment.