feat: add department and add user form in reports

This commit is contained in:
prafull-opensignlabs
2024-06-28 21:12:58 +05:30
parent 7b2b71fea5
commit 17b9fc772e
6 changed files with 254 additions and 312 deletions
+3
View File
@@ -20,6 +20,7 @@ import SSOVerify from "./pages/SSOVerify";
import Loader from "./primitives/Loader";
import DepartmentList from "./pages/DepartmentList";
import UserList from "./pages/UserList";
import AddDepartment from "./components/AddDepartment";
const DebugPdf = lazy(() => import("./pages/DebugPdf"));
const ForgetPassword = lazy(() => import("./pages/ForgetPassword"));
const GuestLogin = lazy(() => import("./pages/GuestLogin"));
@@ -123,6 +124,8 @@ function App() {
)}
<Route element={<HomeLayout />}>
<Route path="/departments" element={<DepartmentList />} />
<Route path="/departmentform" element={<AddDepartment />} />
<Route path="/users" element={<UserList />} />
<Route
+164 -247
View File
@@ -1,6 +1,5 @@
import React, { useEffect, useState } from "react";
import Parse from "parse";
import axios from "axios";
import Title from "./Title";
import Alert from "../primitives/Alert";
import Loader from "../primitives/Loader";
@@ -8,222 +7,167 @@ import Loader from "../primitives/Loader";
const AddDepartment = (props) => {
const [formdata, setFormdata] = useState({
name: "",
phone: "",
email: "",
department: "",
role: ""
department: ""
});
const [isLoader, setIsLoader] = useState(false);
const [isUserExist, setIsUserExist] = useState(false);
const [isAlert, setIsAlert] = useState({ type: "success", msg: "" });
const [departmentList, setDepartmentList] = useState([]);
const role = ["OrgAdmin", "Manager", "User", "Guest"];
const parseBaseUrl = localStorage.getItem("baseUrl");
const parseAppId = localStorage.getItem("parseAppId");
const [parentDepartments, setParentDepartments] = useState([]);
const [level, setLevel] = useState(1);
useEffect(() => {
getDepartmentList();
}, []);
const getDepartmentList = async () => {
const extUser = JSON.parse(localStorage.getItem("Extand_Class"))?.[0];
console.log("extUser ", extUser);
const department = new Parse.Query("contracts_Departments");
department.equalTo("OrganizationId", {
__type: "Pointer",
className: "contracts_Organizations",
objectId: extUser.OrganizationId.objectId
});
department.doesNotExist("DepartmentParentId");
department.doesNotExist("Ancestors");
const departmentRes = await department.find();
if (departmentRes.length > 0) {
const _departmentRes = JSON.parse(JSON.stringify(departmentRes));
setDepartmentList(_departmentRes);
}
};
const checkUserExist = async () => {
const user = Parse.User.current();
try {
const res = await Parse.Cloud.run("getUserDetails", {
email: user.get("email"),
userId: user.id
const extUser = JSON.parse(localStorage.getItem("Extand_Class"))?.[0];
const department = new Parse.Query("contracts_Departments");
department.equalTo("OrganizationId", {
__type: "Pointer",
className: "contracts_Organizations",
objectId: extUser.OrganizationId.objectId
});
if (res) {
return true;
} else {
return false;
department.doesNotExist("ParentId");
department.doesNotExist("Ancestors");
const departmentRes = await department.find();
if (departmentRes.length > 0) {
const _departmentRes = JSON.parse(JSON.stringify(departmentRes));
// console.log("_departmentRes ", _departmentRes);
setDepartmentList(_departmentRes);
}
} catch (err) {
console.log("err", err);
console.log("Err in fetch top level departmentlist", err);
}
};
const fetchDepartmentsbyPtr = async (departmentPtr) => {
setLevel((prev) => prev + 1);
try {
const extUser = JSON.parse(localStorage.getItem("Extand_Class"))?.[0];
const department = new Parse.Query("contracts_Departments");
department.equalTo("ParentId", departmentPtr);
department.equalTo("OrganizationId", {
__type: "Pointer",
className: "contracts_Organizations",
objectId: extUser.OrganizationId.objectId
});
const departmentRes = await department.find();
if (departmentRes.length > 0) {
const _departmentRes = JSON.parse(JSON.stringify(departmentRes));
// console.log("sub", ["DD_" + level] ,_departmentRes)
const departmentName = _departmentRes?.[0]?.ParentId?.Name;
setParentDepartments((prev) => [
...prev,
{
["DD_" + level]: { name: departmentName, opt: _departmentRes }
}
]);
}
} catch (err) {
console.log("Err in fetch departmentlist", err);
}
};
const handleDropdown = (e) => {
setFormdata((prev) => ({ ...prev, [e.target.name]: e.target.value }));
const departmentPtr = {
__type: "Pointer",
className: "contracts_Departments",
objectId: e.target.value
};
// const index = parentDepartments.findIndex((x) => x[e.target.name]);
// setParentDepartments((prev) => prev.slice(0, index +1));
// console.log("index ", index);
fetchDepartmentsbyPtr(departmentPtr);
};
console.log("formdata", formdata);
// Define a function to handle form submission
const handleSubmit = async (e) => {
e.preventDefault();
e.stopPropagation();
const localUser = JSON.parse(localStorage.getItem("Extand_Class"))?.[0];
// Extracting values except for the 'name' key
const ancestors = Object.entries(formdata)
.filter(([key]) => key !== "name")
.map(([key, value]) => value);
setIsLoader(true);
const res = await checkUserExist();
if (res) {
setIsUserExist(true);
setIsLoader(false);
setTimeout(() => {
setIsUserExist(false);
}, 1000);
} else {
try {
const extUser = new Parse.Object("contracts_Users");
extUser.set("Name", formdata.name);
if (formdata.phone) {
extUser.set("Phone", formdata.phone);
try {
const localUser = JSON.parse(localStorage.getItem("Extand_Class"))?.[0];
const ParentId = {
__type: "Pointer",
className: "contracts_Departments",
objectId: ""
};
setIsLoader(true);
const department = new Parse.Query("contracts_Departments");
department.equalTo("Name", formdata.name);
if (ancestors.length > 0) {
ParentId.objectId = "";
department.equalTo("ParentId", ParentId);
}
if (localUser && localUser.OrganizationId) {
department.equalTo("OrganizationId", {
__type: "Pointer",
className: "contracts_Organizations",
objectId: localUser.OrganizationId.objectId
});
}
const isDepartment = await department.first();
if (isDepartment) {
setIsAlert({ type: "info", msg: "Department already exists." });
setIsLoader(false);
} else {
const newDepartment = new Parse.Object("contracts_Departments");
newDepartment.set("Name", formdata.name);
if (ancestors.length > 0) {
newDepartment.set("ParentId", ParentId);
}
extUser.set("Email", formdata.email);
extUser.set("UserRole", `contracts_${formdata.role}`);
extUser.set("DepartmentIds", [
{
__type: "Pointer",
className: "contracts_Departments",
objectId: formdata.department
}
]);
if (localUser && localUser.OrganizationId) {
extUser.set("OrganizationId", {
newDepartment.set("OrganizationId", {
__type: "Pointer",
className: "contracts_Organizations",
objectId: localUser.OrganizationId.objectId
});
}
if (localStorage.getItem("TenantId")) {
extUser.set("TenantId", {
__type: "Pointer",
className: "partners_Tenant",
objectId: localStorage.getItem("TenantId")
const newdepartmentRes = await newDepartment.save();
if (ancestors.length > 0) {
newDepartment.set("ParentId", ParentId);
props.handleDepartmentInfo({
objectId: newdepartmentRes.id,
Name: formdata.name,
ParentId: ParentId,
Ancestors: ancestors,
IsActive: true
});
} else {
props.handleDepartmentInfo({
objectId: newdepartmentRes.id,
Name: formdata.name,
ParentId: "",
Ancestors: "",
IsActive: true
});
}
try {
const _users = Parse.Object.extend("User");
const _user = new _users();
_user.set("name", formdata.name);
_user.set("username", formdata.email);
_user.set("email", formdata.email);
_user.set("password", formdata.email);
if (formdata.phone) {
_user.set("phone", formdata.phone);
}
const user = await _user.save();
if (user) {
const roleurl = `${parseBaseUrl}functions/AddUserToRole`;
const headers = {
"Content-Type": "application/json",
"X-Parse-Application-Id": parseAppId,
sessionToken: localStorage.getItem("accesstoken")
};
const body = {
appName: "contracts",
roleName: "contracts_" + formdata.role,
userId: user.id
};
await axios.post(roleurl, body, { headers: headers });
const currentUser = Parse.User.current();
extUser.set(
"CreatedBy",
Parse.User.createWithoutData(currentUser.id)
);
extUser.set("UserId", user);
const acl = new Parse.ACL();
acl.setPublicReadAccess(true);
acl.setPublicWriteAccess(true);
acl.setReadAccess(currentUser.id, true);
acl.setWriteAccess(currentUser.id, true);
extUser.setACL(acl);
const res = await extUser.save();
const parseData = JSON.parse(JSON.stringify(res));
if (props.closePopup) {
props.closePopup();
}
if (props.handleUserData) {
props.handleUserData(parseData);
}
setIsLoader(false);
setFormdata({
name: "",
email: "",
phone: "",
department: "",
role: ""
});
}
} catch (err) {
console.log("err ", err);
if (err.code === 202) {
const user = Parse.User.current();
const params = { email: user.get("email") };
const userRes = await Parse.Cloud.run("getUserId", params);
const roleurl = `${parseBaseUrl}functions/AddUserToRole`;
const headers = {
"Content-Type": "application/json",
"X-Parse-Application-Id": parseAppId,
sessionToken: localStorage.getItem("accesstoken")
};
const body = {
appName: "contracts",
roleName: "contracts_" + formdata.role,
userId: userRes.id
};
await axios.post(roleurl, body, { headers: headers });
const currentUser = Parse.User.current();
extUser.set(
"CreatedBy",
Parse.User.createWithoutData(currentUser.id)
);
extUser.set("UserId", {
__type: "Pointer",
className: "_User",
objectId: userRes.id
});
const acl = new Parse.ACL();
acl.setPublicReadAccess(true);
acl.setPublicWriteAccess(true);
acl.setReadAccess(currentUser.id, true);
acl.setWriteAccess(currentUser.id, true);
extUser.setACL(acl);
const res = await extUser.save();
const parseData = JSON.parse(JSON.stringify(res));
if (props.closePopup) {
props.closePopup();
}
if (props.handleUserData) {
props.handleUserData(parseData);
}
setIsLoader(false);
setFormdata({
name: "",
email: "",
phone: "",
department: "",
role: ""
});
}
if (props.closePopup) {
props.closePopup();
}
} catch (err) {
console.log("err", err);
setIsLoader(false);
alert("something went wrong!");
setFormdata({
name: "",
department: { name: "", objectId: "" }
});
setIsAlert({
type: "success",
msg: "Department created successfully."
});
}
} catch (err) {
console.log("err in save department", err);
setIsAlert({ type: "danger", msg: "Something went wrong." });
} finally {
setTimeout(() => {
setIsAlert({ type: "success", msg: "" });
}, 1500);
setIsLoader(false);
}
};
@@ -231,10 +175,7 @@ const AddDepartment = (props) => {
const handleReset = () => {
setFormdata({
name: "",
email: "",
phone: "",
department: "",
role: ""
department: { name: "", objectId: "" }
});
};
const handleChange = (e) => {
@@ -243,8 +184,12 @@ const AddDepartment = (props) => {
return (
<div className="shadow-md rounded-box my-[1px] p-3 bg-[#ffffff]">
<Title title={"Add User"} />
{isUserExist && <Alert type="danger">User already exists!</Alert>}
<Title title={"Add Department"} />
{isAlert.msg && (
<Alert type={isAlert.type}>
<div className="ml-3">{isAlert.msg}</div>
</Alert>
)}
{isLoader && (
<div className="fixed inset-0 flex justify-center items-center bg-black bg-opacity-30 z-50 rounded-box">
<Loader />
@@ -270,40 +215,7 @@ const AddDepartment = (props) => {
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
/>
</div>
<div className="mb-3">
<label
htmlFor="email"
className="block text-xs text-gray-700 font-semibold"
>
Email
<span className="text-[red] text-[13px]"> *</span>
</label>
<input
type="email"
name="email"
value={formdata.email}
onChange={(e) => handleChange(e)}
required
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
/>
</div>
<div className="mb-3">
<label
htmlFor="phone"
className="block text-xs text-gray-700 font-semibold"
>
Phone
{/* <span className="text-[red] text-[13px]"> *</span> */}
</label>
<input
type="text"
name="phone"
value={formdata.phone}
onChange={(e) => handleChange(e)}
// required
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
/>
</div>
<div className="mb-3">
<label
htmlFor="phone"
@@ -314,11 +226,11 @@ const AddDepartment = (props) => {
</label>
<select
value={formdata.department}
onChange={(e) => handleChange(e)}
onChange={(e) => handleDropdown(e)}
name="department"
className="op-select op-select-bordered op-select-sm focus:outline-none hover:border-base-content w-full text-xs"
>
<option disabled>select</option>
<option>select</option>
{departmentList.length > 0 &&
departmentList.map((x) => (
<option key={x.objectId} value={x.objectId}>
@@ -327,28 +239,33 @@ const AddDepartment = (props) => {
))}
</select>
</div>
<div className="mb-3">
<label
htmlFor="phone"
className="block text-xs text-gray-700 font-semibold"
>
Role
{/* <span className="text-[red] text-[13px]"> *</span> */}
</label>
<select
value={formdata.role}
onChange={(e) => handleChange(e)}
name="role"
className="op-select op-select-bordered op-select-sm focus:outline-none hover:border-base-content w-full text-xs"
>
{role.length > 0 &&
role.map((x) => (
<option key={x} value={x}>
{x}
{parentDepartments?.map((x, i) => (
<div className="mb-3" key={"DD_" + (i + 1)}>
<label
htmlFor="phone"
className="block text-xs text-gray-700 font-semibold"
>
{x["DD_" + (i + 1)]?.name} department
{/* <span className="text-[red] text-[13px]"> *</span> */}
</label>
<select
value={formdata["DD_" + (i + 1)]}
onChange={(e) => handleDropdown(e)}
name={"DD_" + (i + 1)}
className="op-select op-select-bordered op-select-sm focus:outline-none hover:border-base-content w-full text-xs"
>
<option>select</option>
{x["DD_" + (i + 1)]?.opt?.map((subdepartment) => (
<option
key={subdepartment.objectId}
value={subdepartment.objectId}
>
{subdepartment.Name}
</option>
))}
</select>
</div>
</select>
</div>
))}
<div className="flex items-center mt-3 gap-2 text-white">
<button type="submit" className="op-btn op-btn-primary">
Submit
+4 -4
View File
@@ -26,7 +26,6 @@ const AddUser = (props) => {
const getDepartmentList = async () => {
const extUser = JSON.parse(localStorage.getItem("Extand_Class"))?.[0];
console.log("extUser ", extUser);
const department = new Parse.Query("contracts_Departments");
department.equalTo("OrganizationId", {
__type: "Pointer",
@@ -55,7 +54,6 @@ const AddUser = (props) => {
console.log("err", err);
}
};
console.log("formdata", formdata);
// Define a function to handle form submission
const handleSubmit = async (e) => {
e.preventDefault();
@@ -308,13 +306,14 @@ const AddUser = (props) => {
className="block text-xs text-gray-700 font-semibold"
>
Department
{/* <span className="text-[red] text-[13px]"> *</span> */}
<span className="text-[red] text-[13px]"> *</span>
</label>
<select
value={formdata.department}
onChange={(e) => handleChange(e)}
name="department"
className="op-select op-select-bordered op-select-sm focus:outline-none hover:border-base-content w-full text-xs"
required
>
<option disabled>select</option>
{departmentList.length > 0 &&
@@ -331,13 +330,14 @@ const AddUser = (props) => {
className="block text-xs text-gray-700 font-semibold"
>
Role
{/* <span className="text-[red] text-[13px]"> *</span> */}
<span className="text-[red] text-[13px]"> *</span>
</label>
<select
value={formdata.role}
onChange={(e) => handleChange(e)}
name="role"
className="op-select op-select-bordered op-select-sm focus:outline-none hover:border-base-content w-full text-xs"
required
>
{role.length > 0 &&
role.map((x) => (
+81 -50
View File
@@ -6,26 +6,19 @@ import { useLocation } from "react-router-dom";
import Tooltip from "../primitives/Tooltip";
import ModalUi from "../primitives/ModalUi";
import pad from "../assets/images/pad.svg";
import AddDepartment from "../components/AddDepartment";
const heading = ["Sr.No", "Name", "Actions"];
const actions = [
{
btnId: "1231",
hoverLabel: "Edit",
btnColor: "op-btn-primary",
btnIcon: "fa-light fa-pen",
redirectUrl: "draftDocument",
action: "redirect"
},
{
btnId: "2142",
hoverLabel: "Delete",
btnColor: "op-btn-secondary",
btnIcon: "fa-light fa-trash",
redirectUrl: "",
action: "delete"
}
];
const heading = ["Sr.No", "Name", "Parent Department", "Status"];
// const actions = [
// {
// btnId: "1231",
// hoverLabel: "Edit",
// btnColor: "op-btn-primary",
// btnIcon: "fa-light fa-pen",
// redirectUrl: "draftDocument",
// action: "redirect"
// }
// ];
const DepartmentList = () => {
const recordperPage = 10;
@@ -36,7 +29,7 @@ const DepartmentList = () => {
const isDashboard =
location?.pathname === "/dashboard/35KBoSgoAK" ? true : false;
const [currentPage, setCurrentPage] = useState(1);
const [isDeleteModal, setIsDeleteModal] = useState(false);
const [isActiveModal, setIsActiveModal] = useState(false);
const [isAlert, setIsAlert] = useState({ type: "success", msg: "" });
const startIndex = (currentPage - 1) * recordperPage; // user per page
@@ -127,19 +120,39 @@ const DepartmentList = () => {
const indexOfLastDoc = currentPage * recordperPage;
const indexOfFirstDoc = indexOfLastDoc - recordperPage;
const currentList = departmentList?.slice(indexOfFirstDoc, indexOfLastDoc);
const handleDelete = () => {};
const handleClose = () => {
setIsDeleteModal({});
setIsActiveModal({});
};
// Change page
const paginateFront = () => setCurrentPage(currentPage + 1);
const paginateBack = () => setCurrentPage(currentPage - 1);
const handleActionBtn = (act, item) => {
if (act.action === "delete") {
setIsDeleteModal({ [item.objectId]: true });
// const handleActionBtn = (act, item) => {
// // if (act.action === "delete") {
// // setIsDeleteModal({ [item.objectId]: true });
// // }
// };
const handleToggleBtn = (department) => {
setIsActiveModal({ [department.objectId]: true });
};
const handleToggleSubmit = (department) => {
const index = departmentList.findIndex(
(obj) => obj.objectId === department.objectId
);
if (index !== -1) {
const newArray = [...departmentList];
newArray[index] = {
...newArray[index],
IsActive: !newArray[index].IsActive
};
setDepartmentList(newArray);
setIsActiveModal({});
}
};
const handleDepartmentInfo = (department) => {
setDepartmentList((prev) => [department, ...prev]);
};
return (
<div className="relative">
{isLoader && (
@@ -170,12 +183,6 @@ const DepartmentList = () => {
<th className="px-4 py-2">{item}</th>
</React.Fragment>
))}
{actions?.length > 0 && (
<th className="px-4 py-2 text-transparent pointer-events-none">
Action
</th>
)}
</tr>
</thead>
<tbody className="text-[12px]">
@@ -186,35 +193,34 @@ const DepartmentList = () => {
{heading.includes("Sr.No") && (
<th className="px-4 py-2">{startIndex + index + 1}</th>
)}
<td className="px-4 py-2 font-semibold">{item?.Name} </td>
<td className="px-3 py-2 text-white flex flex-wrap gap-1">
{actions?.length > 0 &&
actions.map((act, index) => (
<button
key={index}
onClick={() => handleActionBtn(act, item)}
title={act.hoverLabel}
className={`${
act?.btnColor ? act.btnColor : ""
} op-btn op-btn-sm w-[50px]`}
>
<i className={act.btnIcon}></i>
</button>
))}
{isDeleteModal[item.objectId] && (
<td className="px-4 py-2 font-semibold">{item?.Name}</td>
<td className="px-4 py-2 font-semibold">
{item?.ParentId?.Name || "-"}
</td>
<td className="px-4 py-2 font-semibold">
<label className="cursor-pointer relative block items-center mb-0">
<input
type="checkbox"
className="op-toggle transition-all op-toggle-secondary"
checked={item?.IsActive}
onChange={() => handleToggleBtn(item)}
/>
</label>
{isActiveModal[item.objectId] && (
<ModalUi
isOpen
title={"Delete Department"}
title={"Department status"}
handleClose={handleClose}
>
<div className="m-[20px]">
<div className="text-lg font-normal text-black">
Are you sure you want to delete this department?
Are you sure you want to disable this
department?
</div>
<hr className="bg-[#ccc] mt-4 " />
<div className="flex items-center mt-3 gap-2 text-white">
<button
onClick={() => handleDelete(item)}
onClick={() => handleToggleSubmit(item)}
className="op-btn op-btn-primary"
>
Yes
@@ -230,6 +236,21 @@ const DepartmentList = () => {
</ModalUi>
)}
</td>
{/* <td className="px-3 py-2 text-white flex flex-wrap gap-1">
{actions?.length > 0 &&
actions.map((act, index) => (
<button
key={index}
onClick={() => handleActionBtn(act, item)}
title={act.hoverLabel}
className={`${
act?.btnColor ? act.btnColor : ""
} op-btn op-btn-sm w-[50px]`}
>
<i className={act.btnIcon}></i>
</button>
))}
</td> */}
</tr>
))}
</>
@@ -283,6 +304,16 @@ const DepartmentList = () => {
<div className="text-sm font-semibold">No Data Available</div>
</div>
)}
<ModalUi
title={"Add Department"}
isOpen={isModal}
handleClose={handleFormModal}
>
<AddDepartment
handleDepartmentInfo={handleDepartmentInfo}
closePopup={handleFormModal}
/>
</ModalUi>
</div>
</div>
);
-6
View File
@@ -160,12 +160,6 @@ const UserList = () => {
<th className="px-4 py-2">{item}</th>
</React.Fragment>
))}
{actions?.length > 0 && (
<th className="px-4 py-2 text-transparent pointer-events-none">
Action
</th>
)}
</tr>
</thead>
<tbody className="text-[12px]">
+2 -5
View File
@@ -204,10 +204,7 @@ app.use('/v1', v1);
// Parse Server plays nicely with the rest of your web routes
app.get('/', function (req, res) {
// res.statusCode = 200;
// res.setHeader('Content-Type', 'text/plain');
// res.end('I dream of being a website. Please star the parse-server repo on GitHub!');
res.status(200).send('open-sign-server is running !!!');
res.status(200).send('opensign-server is running !!!');
});
if (!process.env.TESTING) {
@@ -217,7 +214,7 @@ if (!process.env.TESTING) {
httpServer.keepAliveTimeout = 100000; // in milliseconds
httpServer.headersTimeout = 100000; // in milliseconds
httpServer.listen(port, '0.0.0.0', function () {
console.log('parse-server-example running on port ' + port + '.');
console.log('opensign-server running on port ' + port + '.');
const isWindows = process.platform === 'win32';
// console.log('isWindows', isWindows);