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 Aug 11, 2022
1 parent 133c1af commit e22b654
Show file tree
Hide file tree
Showing 10 changed files with 314 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 @@ -91,6 +91,7 @@ const UploadDelete = React.lazy(() => import("pages/Organize/Uploads/Delete"));
// Admin Pages
const GroupCreate = React.lazy(() => import("pages/Admin/Group/Create"));
const DeleteUser = React.lazy(() => import("pages/Admin/Users/Delete"));
const ManageGroup = React.lazy(() => import("pages/Admin/Group/Manage"));
const AddLicense = React.lazy(() => import("pages/Admin/License/Create"));
const SelectLicense = React.lazy(() =>
import("pages/Admin/License/SelectLicense")
Expand Down Expand Up @@ -284,6 +285,11 @@ const Routes = () => {
path={routes.admin.group.create}
component={GroupCreate}
/>
<AdminLayout
exact
path={routes.admin.group.manageGroup}
component={ManageGroup}
/>
<AdminLayout
exact
path={routes.admin.license.create}
Expand Down
27 changes: 27 additions & 0 deletions src/api/groups.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,30 @@ export const createGroupApi = (name) => {
addGroupName: false,
});
};

// Get all group members
export const getAllGroupMembersApi = (groupId) => {
const url = endpoints.admin.groups.getAllGroupMembers(groupId);
return sendRequest({
url,
method: "GET",
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,
},
});
};
97 changes: 97 additions & 0 deletions src/components/Admin/ChangePermission.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
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 } from "services/groups";

import PropTypes from "prop-types";

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

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

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

const handleSetNewPermission = async (newPerm) => {
setSelectedPerm(newPerm);
try {
const res = await changeUserPermission(
currGroup,
member?.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>{member?.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,
member: 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 @@ -255,9 +255,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 @@ -260,3 +260,23 @@ export const initialMantainanceFields = {
rmvRepoOldFiles1: false,
rmvRepoOldFiles2: false,
};

// eslint-disable-next-line camelcase
export const userPermissions = [
{
id: -1,
name: "None",
},
{
id: 0,
name: "User",
},
{
id: 1,
name: "Admin",
},
{
id: 2,
name: "Advisor",
},
];
3 changes: 3 additions & 0 deletions src/constants/endpoints.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ const endpoints = {
groups: {
create: () => `${apiUrl}/groups`,
getAll: () => `${apiUrl}/groups`,
getAllGroupMembers: (groupId) => `${apiUrl}/groups/${groupId}/members`,
changeUserPermission: (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: {
delete: "/admin/users/delete",
Expand Down
135 changes: 135 additions & 0 deletions src/pages/Admin/Group/Manage/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
/*
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";

// Title
import Title from "components/Title";

// Widgets
import { Alert, InputContainer } from "components/Widgets";

// Required functions for calling APIs
import { fetchAllGroupMembers, fetchAllGroups } from "services/groups";

// Required page components
import ChangePermissionContainer from "components/Admin/ChangePermission";

const ManageGroup = () => {
const initialMessage = {
type: "success",
text: "",
};

const [currGroup, setCurrentGroup] = useState(null);
const [groupMembers, setGroupMembers] = useState([]);
const [groups, setGroups] = useState([]);

const [showMessage, setShowMessage] = useState(false);
const [message, setMessage] = useState(initialMessage);

useEffect(async () => {
try {
const res = await fetchAllGroups();
const resGrpMembers = await fetchAllGroupMembers(res[0].id);
setCurrentGroup(res[0].id);
setGroups(res);
setGroupMembers(resGrpMembers);
} catch (e) {
setMessage({
type: "danger",
text: e.message,
});
}
}, []);

const handleFetchGroupMembers = async (groupId) => {
try {
const res = await fetchAllGroupMembers(groupId);
setGroupMembers(res);
} catch (error) {
setMessage({
type: "danger",
text: error.message,
});
}
};

const handleGroupChange = async (e) => {
setCurrentGroup(e.target.value);
await handleFetchGroupMembers(e.target.value);
};

return (
<>
<Title title="Manage Group Users" />
<div className="main-container my-3">
{showMessage && (
<Alert
type={message.type}
setShow={setShowMessage}
message={message.text}
/>
)}
<h1 className="font-size-main-heading">Manage Group Users</h1>
<br />
<div className="row">
<div className="col-12 col-lg-8">
<form>
<InputContainer
type="select"
name="name"
options={groups}
id="select-tag"
property="name"
onChange={(e) => handleGroupChange(e)}
value={currGroup}
>
Select group to manage:
</InputContainer>
</form>

<table className="table table-striped table-bordered rounded mt-5">
<thead className="bg-dark text-light font-weight-bold">
<tr>
<th>User</th>
<th>Permission</th>
</tr>
</thead>
<tbody>
{groupMembers?.map((member) => (
<ChangePermissionContainer
currGroup={currGroup}
member={member}
handleFetchGroupMembers={handleFetchGroupMembers}
perm={member.group_perm}
setShowMessage={setShowMessage}
setMessage={setMessage}
key={member.user.id}
/>
))}
</tbody>
</table>
</div>
</div>
</div>
</>
);
};

export default ManageGroup;
21 changes: 20 additions & 1 deletion src/services/groups.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

import { getAllGroupsApi, createGroupApi } from "api/groups";
import {
getAllGroupsApi,
createGroupApi,
getAllGroupMembersApi,
changeUserPermissionApi,
} from "api/groups";
import { setLocalStorage, getLocalStorage } from "shared/storageHelper";

// Fetching all the groups
Expand All @@ -37,3 +42,17 @@ export const createGroup = (name) => {
return res;
});
};

// Get all group members
export const fetchAllGroupMembers = (groupId) => {
return getAllGroupMembersApi(groupId).then((res) => {
return res;
});
};

// Change user permission
export const changeUserPermission = (groupId, userId, permission) => {
return changeUserPermissionApi(groupId, userId, permission).then((res) => {
return res;
});
};

0 comments on commit e22b654

Please sign in to comment.