feat: add departmentlist and userlist page

This commit is contained in:
prafull-opensignlabs
2024-06-27 19:00:55 +05:30
parent cc398d68e4
commit 2c715a77a2
14 changed files with 914 additions and 290 deletions
+5
View File
@@ -18,6 +18,8 @@ import LazyPage from "./primitives/LazyPage";
import { isEnableSubscription } from "./constant/const";
import SSOVerify from "./pages/SSOVerify";
import Loader from "./primitives/Loader";
import DepartmentList from "./pages/DepartmentList";
import UserList from "./pages/UserList";
const DebugPdf = lazy(() => import("./pages/DebugPdf"));
const ForgetPassword = lazy(() => import("./pages/ForgetPassword"));
const GuestLogin = lazy(() => import("./pages/GuestLogin"));
@@ -120,6 +122,9 @@ function App() {
</>
)}
<Route element={<HomeLayout />}>
<Route path="/departments" element={<DepartmentList />} />
<Route path="/users" element={<UserList />} />
<Route
path="/changepassword"
element={<LazyPage Page={ChangePassword} />}
+115 -65
View File
@@ -1,4 +1,4 @@
import React, { useState } from "react";
import React, { useEffect, useState } from "react";
import Parse from "parse";
import axios from "axios";
import Title from "./Title";
@@ -6,19 +6,44 @@ import Alert from "../primitives/Alert";
import Loader from "../primitives/Loader";
const AddUser = (props) => {
const [name, setName] = useState("");
const [phone, setPhone] = useState("");
const [email, setEmail] = useState("");
const [formdata, setFormdata] = useState({
name: "",
phone: "",
email: "",
department: "",
role: ""
});
const [isLoader, setIsLoader] = useState(false);
const [isUserExist, setIsUserExist] = useState(false);
const [departmentList, setDepartmentList] = useState([]);
const parseBaseUrl = localStorage.getItem("baseUrl");
const parseAppId = localStorage.getItem("parseAppId");
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
});
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: email,
userId: Parse.User.current().id
email: user.get("email"),
userId: user.id
});
if (res) {
return true;
@@ -43,14 +68,16 @@ const AddUser = (props) => {
}, 1000);
} else {
try {
const contactQuery = new Parse.Object("contracts_Users");
contactQuery.set("Name", name);
contactQuery.set("Phone", phone);
contactQuery.set("Email", email);
contactQuery.set("UserRole", "contracts_User");
const extUser = new Parse.Object("contracts_Users");
extUser.set("Name", formdata.name);
if (formdata.phone) {
extUser.set("Phone", formdata.phone);
}
extUser.set("Email", formdata.email);
extUser.set("UserRole", "contracts_User");
if (localStorage.getItem("TenantId")) {
contactQuery.set("TenantId", {
extUser.set("TenantId", {
__type: "Pointer",
className: "partners_Tenant",
objectId: localStorage.getItem("TenantId")
@@ -60,12 +87,12 @@ const AddUser = (props) => {
try {
const _users = Parse.Object.extend("User");
const _user = new _users();
_user.set("name", name);
_user.set("username", email);
_user.set("email", email);
_user.set("password", email);
if (phone) {
_user.set("phone", phone);
_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();
@@ -83,29 +110,24 @@ const AddUser = (props) => {
};
await axios.post(roleurl, body, { headers: headers });
const currentUser = Parse.User.current();
contactQuery.set(
extUser.set(
"CreatedBy",
Parse.User.createWithoutData(currentUser.id)
);
contactQuery.set("UserId", user);
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);
contactQuery.setACL(acl);
extUser.setACL(acl);
const res = await contactQuery.save();
const res = await extUser.save();
const parseData = JSON.parse(JSON.stringify(res));
if (props.details) {
props.details({
value: parseData[props.valueKey],
label: parseData[props.displayKey]
});
}
if (props.closePopup) {
props.closePopup();
}
@@ -114,15 +136,19 @@ const AddUser = (props) => {
}
setIsLoader(false);
setName("");
setPhone("");
setEmail("");
setFormdata({
name: "",
email: "",
phone: "",
department: "",
role: ""
});
}
} catch (err) {
console.log("err ", err);
if (err.code === 202) {
const params = { email: email };
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 = {
@@ -137,12 +163,12 @@ const AddUser = (props) => {
};
await axios.post(roleurl, body, { headers: headers });
const currentUser = Parse.User.current();
contactQuery.set(
extUser.set(
"CreatedBy",
Parse.User.createWithoutData(currentUser.id)
);
contactQuery.set("UserId", {
extUser.set("UserId", {
__type: "Pointer",
className: "_User",
objectId: userRes.id
@@ -153,16 +179,10 @@ const AddUser = (props) => {
acl.setReadAccess(currentUser.id, true);
acl.setWriteAccess(currentUser.id, true);
contactQuery.setACL(acl);
const res = await contactQuery.save();
extUser.setACL(acl);
const res = await extUser.save();
const parseData = JSON.parse(JSON.stringify(res));
if (props.details) {
props.details({
value: parseData[props.valueKey],
label: parseData[props.displayKey]
});
}
if (props.closePopup) {
props.closePopup();
}
@@ -170,9 +190,13 @@ const AddUser = (props) => {
props.handleUserData(parseData);
}
setIsLoader(false);
setName("");
setPhone("");
setEmail("");
setFormdata({
name: "",
email: "",
phone: "",
department: "",
role: ""
});
}
}
} catch (err) {
@@ -185,13 +209,20 @@ const AddUser = (props) => {
// Define a function to handle the "add yourself" checkbox
const handleReset = () => {
setName("");
setPhone("");
setEmail("");
setFormdata({
name: "",
email: "",
phone: "",
department: "",
role: ""
});
};
const handleChange = (e) => {
setFormdata((prev) => ({ ...prev, [e.target.name]: e.target.value }));
};
return (
<div className="shadow-md rounded my-2 p-3 bg-[#ffffff] md:border-[1px] md:border-gray-600/50">
<div className="shadow-md rounded-box my-[1px] p-3 bg-[#ffffff]">
<Title title={"Add User"} />
{isUserExist && <Alert type="danger">User already exists!</Alert>}
{isLoader && (
@@ -201,7 +232,7 @@ const AddUser = (props) => {
)}
<div className="w-full mx-auto">
<form onSubmit={handleSubmit}>
<h1 className="text-[20px] font-semibold mb-4">Add User</h1>
{/* <h1 className="text-[20px] font-semibold mb-4">Add User</h1> */}
<div className="mb-3">
<label
htmlFor="name"
@@ -213,8 +244,8 @@ const AddUser = (props) => {
<input
type="text"
id="name"
value={name}
onChange={(e) => setName(e.target.value)}
value={formdata.name}
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"
/>
@@ -230,8 +261,8 @@ const AddUser = (props) => {
<input
type="email"
id="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
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"
/>
@@ -242,29 +273,48 @@ const AddUser = (props) => {
className="block text-xs text-gray-700 font-semibold"
>
Phone
<span className="text-[red] text-[13px]"> *</span>
{/* <span className="text-[red] text-[13px]"> *</span> */}
</label>
<input
type="text"
id="phone"
value={phone}
onChange={(e) => setPhone(e.target.value)}
required
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="flex items-center mt-3 gap-2 text-white">
<button
type="submit"
className="bg-[#1ab6ce] rounded-sm shadow-md text-[13px] font-semibold uppercase text-white py-1.5 px-2.5 focus:outline-none"
<div className="mb-3">
<label
htmlFor="phone"
className="block text-xs text-gray-700 font-semibold"
>
Department
{/* <span className="text-[red] text-[13px]"> *</span> */}
</label>
<select
value={formdata.department}
onChange={(e) => handleChange(e)}
id="department"
className="op-select op-select-bordered op-select-sm focus:outline-none hover:border-base-content w-full text-xs"
>
<option>select</option>
{departmentList.length > 0 &&
departmentList.map((x) => (
<option key={x.objectId} value={x.objectId}>
{x.Name}
</option>
))}
</select>
</div>
<div className="flex items-center mt-3 gap-2 text-white">
<button type="submit" className="op-btn op-btn-primary">
Submit
</button>
<div
type="button"
onClick={() => handleReset()}
className="bg-[#188ae2] rounded-sm shadow-md text-[13px] font-semibold uppercase text-white py-1.5 px-2.5 text-center ml-[2px] focus:outline-none"
className="op-btn op-btn-secondary"
>
Reset
</div>
+16
View File
@@ -154,6 +154,22 @@ const sidebarList = [
pageType: "webhook",
description: "",
objectId: ""
},
{
icon: "fa-light fa-building-memo",
title: "Departments",
target: "_self",
pageType: "",
description: "",
objectId: "departments"
},
{
icon: "fa-light fa-building-memo",
title: "Users",
target: "_self",
pageType: "",
description: "",
objectId: "users"
}
]
}
+262
View File
@@ -0,0 +1,262 @@
import React, { useEffect, useState } from "react";
import Parse from "parse";
import Alert from "../primitives/Alert";
import Loader from "../primitives/Loader";
import { useLocation, useNavigate } from "react-router-dom";
import Tooltip from "../primitives/Tooltip";
import ModalUi from "../primitives/ModalUi";
import pad from "../assets/images/pad.svg";
const heading = ["Sr.No", "Name"];
const actions = [];
const DepartmentList = () => {
const recordperPage = 10;
const [departmentList, setDepartmentList] = useState([]);
const [isLoader, setIsLoader] = useState(false);
const [isModal, setIsModal] = useState(false);
const navigate = useNavigate();
const location = useLocation();
const isDashboard =
location?.pathname === "/dashboard/35KBoSgoAK" ? true : false;
const [currentPage, setCurrentPage] = useState(1);
const [isDeleteModal, setIsDeleteModal] = useState(false);
const [isAlert, setIsAlert] = useState({ type: "success", msg: "" });
const startIndex = (currentPage - 1) * recordperPage; // user per page
const getPaginationRange = () => {
const totalPageNumbers = 7; // Adjust this value to show more/less page numbers
const pages = [];
const totalPages = Math.ceil(departmentList / recordperPage);
if (totalPages <= totalPageNumbers) {
for (let i = 1; i <= totalPages; i++) {
pages.push(i);
}
} else {
const leftSiblingIndex = Math.max(currentPage - 1, 1);
const rightSiblingIndex = Math.min(currentPage + 1, totalPages);
const showLeftDots = leftSiblingIndex > 2;
const showRightDots = rightSiblingIndex < totalPages - 2;
const firstPageIndex = 1;
const lastPageIndex = totalPages;
if (!showLeftDots && showRightDots) {
let leftItemCount = 3;
let leftRange = Array.from({ length: leftItemCount }, (_, i) => i + 1);
pages.push(...leftRange);
pages.push("...");
pages.push(totalPages);
} else if (showLeftDots && !showRightDots) {
let rightItemCount = 3;
let rightRange = Array.from(
{ length: rightItemCount },
(_, i) => totalPages - rightItemCount + i + 1
);
pages.push(firstPageIndex);
pages.push("...");
pages.push(...rightRange);
} else if (showLeftDots && showRightDots) {
let middleRange = Array.from(
{ length: 3 },
(_, i) => leftSiblingIndex + i
);
pages.push(firstPageIndex);
pages.push("...");
pages.push(...middleRange);
pages.push("...");
pages.push(lastPageIndex);
}
}
return pages;
};
const pageNumbers = getPaginationRange();
useEffect(() => {
fetchDepartmentList();
}, []);
async function fetchDepartmentList() {
try {
setIsLoader(true);
const organization = JSON.parse(localStorage.getItem("Extand_Class"));
const department = new Parse.Query("contracts_Departments");
department.equalTo("OrganizationId", organization[0].objectId);
const departmentRes = await department.find();
const _departmentRes = JSON.parse(JSON.stringify(departmentRes));
setDepartmentList(_departmentRes);
} catch (err) {
console.log("Err ", err);
} finally {
setIsLoader(false);
}
}
const handleFormModal = () => {
setIsModal(!isModal);
};
// Get current list
const indexOfLastDoc = currentPage * recordperPage;
const indexOfFirstDoc = indexOfLastDoc - recordperPage;
const currentList = departmentList?.slice(indexOfFirstDoc, indexOfLastDoc);
const handleDelete = () => {};
const handleClose = () => {};
// Change page
const paginateFront = () => setCurrentPage(currentPage + 1);
const paginateBack = () => setCurrentPage(currentPage - 1);
const handleActionBtn = () => {};
return (
<div className="relative">
{isLoader && (
<div className="absolute w-full h-full flex justify-center items-center bg-black bg-opacity-30 z-30">
<Loader />
</div>
)}
<div className="p-2 w-full bg-base-100 text-base-content op-card shadow-lg">
{isAlert && <Alert type={isAlert.type}>{isAlert.message}</Alert>}
<div className="flex flex-row items-center justify-between my-2 mx-3 text-[20px] md:text-[23px]">
<div className="font-light">
department list{" "}
<span className="text-xs md:text-[13px] font-normal">
<Tooltip message={"department list"} />
</span>
</div>
<div className="cursor-pointer" onClick={() => handleFormModal()}>
<i className="fa-light fa-square-plus text-accent text-[40px]"></i>
</div>
</div>
<div className={` overflow-x-auto w-full`}>
<table className="op-table border-collapse w-full">
<thead className="text-[14px]">
<tr className="border-y-[1px]">
{heading?.map((item, index) => (
<React.Fragment key={index}>
<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]">
{departmentList?.length > 0 && (
<>
{currentList.map((item, index) => (
<tr className="border-y-[1px]" key={index}>
{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-4 py-2 ">{item?.Email || "-"}</td>
<td className="px-4 py-2">{item?.Phone || "-"}</td>
<td className="px-3 py-2 text-white grid grid-cols-2">
{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`}
>
<i className={act.btnIcon}></i>
</button>
))}
{isDeleteModal[item.objectId] && (
<ModalUi
isOpen
title={"Delete Contact"}
handleClose={handleClose}
>
<div className="m-[20px]">
<div className="text-lg font-normal text-black">
Are you sure you want to delete this contact?
</div>
<hr className="bg-[#ccc] mt-4 " />
<div className="flex items-center mt-3 gap-2 text-white">
<button
onClick={() => handleDelete(item)}
className="op-btn op-btn-primary"
>
Yes
</button>
<button
onClick={handleClose}
className="op-btn op-btn-secondary"
>
No
</button>
</div>
</div>
</ModalUi>
)}
</td>
</tr>
))}
</>
)}
</tbody>
</table>
</div>
<div className="op-join flex flex-wrap items-center p-2">
{departmentList.length > recordperPage && (
<button
onClick={() => paginateBack()}
className="op-join-item op-btn op-btn-sm"
>
Prev
</button>
)}
{pageNumbers.map((x, i) => (
<button
key={i}
onClick={() => setCurrentPage(x)}
disabled={x === "..."}
className={`${
x === currentPage ? "op-btn-active" : ""
} op-join-item op-btn op-btn-sm`}
>
{x}
</button>
))}
{departmentList.length > recordperPage && (
<button
onClick={() => paginateFront()}
className="op-join-item op-btn op-btn-sm"
>
Next
</button>
)}
</div>
{departmentList?.length <= 0 && (
<div
className={`${
isDashboard ? "h-[317px]" : ""
} flex flex-col items-center justify-center w-ful bg-base-100 text-base-content rounded-xl py-4`}
>
<div className="w-[60px] h-[60px] overflow-hidden">
<img
className="w-full h-full object-contain"
src={pad}
alt="img"
/>
</div>
<div className="text-sm font-semibold">No Data Available</div>
</div>
)}
</div>
</div>
);
};
export default DepartmentList;
+174 -216
View File
@@ -110,193 +110,115 @@ function Login() {
"X-Parse-Application-Id": parseAppId,
sessionToken: _user.sessionToken
};
let body = {
appname: localStorage.getItem("_appName")
};
const body = { appname: "contracts" };
await axios
.post(url, JSON.stringify(body), { headers: headers })
.then((axiosRes) => {
.then(async (axiosRes) => {
const roles = axiosRes.data.result;
if (roles) {
userRoles = roles;
let _currentRole = "";
const valuesToExclude = [
"contracts_Guest",
`${localStorage.getItem("_appName")}_appeditor`
];
if (userRoles.length > 1) {
const rolesfiltered = userRoles.filter(
(x) => !valuesToExclude.includes(x)
);
if (rolesfiltered.length > 0) {
_currentRole = rolesfiltered[0];
}
} else {
const rolesfiltered = userRoles.filter(
(x) => !valuesToExclude.includes(x)
);
if (rolesfiltered.length > 0) {
_currentRole = userRoles[0];
} else {
_currentRole = "";
}
}
if (
_currentRole &&
_currentRole !==
`${localStorage.getItem("_appName")}_appeditor`
) {
userSettings.forEach(async (element) => {
const redirectUrl =
location?.state?.from ||
`/${element.pageType}/${element.pageId}`;
if (element.role === _currentRole) {
let _role = _currentRole.replace(
`${localStorage.getItem("_appName")}_`,
""
const currentUser = Parse.User.current();
await Parse.Cloud.run("getUserDetails", {
email: currentUser.get("email")
})
.then((extUser) => {
if (roles) {
userRoles = roles;
let _currentRole = "";
if (userRoles.length > 0) {
_currentRole = userRoles.find(
(x) => x === extUser.get("UserRole")
);
localStorage.setItem("_user_role", _role);
// Get TenentID from Extendend Class
localStorage.setItem(
"extended_class",
element.extended_class
);
const currentUser = Parse.User.current();
await Parse.Cloud.run("getUserDetails", {
email: currentUser.get("email")
}).then(
async (result) => {
let tenentInfo = [];
const results = [result];
if (results) {
let extendedInfo_stringify =
JSON.stringify(results);
localStorage.setItem(
"Extand_Class",
extendedInfo_stringify
);
let extendedInfo = JSON.parse(
extendedInfo_stringify
);
if (extendedInfo.length > 1) {
extendedInfo.forEach((x) => {
if (x.TenantId) {
let obj = {
tenentId: x.TenantId.objectId,
tenentName:
x.TenantId.TenantName || ""
};
tenentInfo.push(obj);
}
});
if (tenentInfo.length) {
dispatch(
showTenant(
tenentInfo[0].tenentName || ""
)
);
localStorage.setItem(
"TenantName",
tenentInfo[0].tenentName || ""
);
}
userSettings.forEach(async (element) => {
const redirectUrl =
location?.state?.from ||
`/${element.pageType}/${element.pageId}`;
if (element.role === _currentRole) {
let _role = _currentRole.replace(
"contracts_",
""
);
localStorage.setItem("_user_role", _role);
// Get TenentID from Extendend Class
localStorage.setItem(
"extended_class",
element.extended_class
);
let tenentInfo = [];
const results = [extUser];
if (results) {
let extendedInfo_stringify =
JSON.stringify(results);
localStorage.setItem(
"Extand_Class",
extendedInfo_stringify
);
let extendedInfo = JSON.parse(
extendedInfo_stringify
);
if (extendedInfo.length > 1) {
extendedInfo.forEach((x) => {
if (x.TenantId) {
let obj = {
tenentId: x.TenantId.objectId,
tenentName:
x.TenantId.TenantName || ""
};
tenentInfo.push(obj);
}
});
if (tenentInfo.length) {
dispatch(
showTenant(
tenentInfo[0].tenentName || ""
)
);
localStorage.setItem(
"TenantName",
tenentInfo[0].tenentName || ""
);
}
localStorage.setItem("showpopup", true);
localStorage.setItem(
"PageLanding",
element.pageId
);
localStorage.setItem(
"defaultmenuid",
element.menuId
);
localStorage.setItem(
"pageType",
element.pageType
);
setState({ ...state, loading: false });
navigate("/");
} else {
extendedInfo.forEach((x) => {
if (x.TenantId) {
let obj = {
tenentId: x.TenantId.objectId,
tenentName:
x.TenantId.TenantName || ""
};
localStorage.setItem(
"TenantId",
x.TenantId.objectId
);
tenentInfo.push(obj);
}
});
if (tenentInfo.length) {
dispatch(
showTenant(
tenentInfo[0].tenentName || ""
)
);
localStorage.setItem(
"TenantName",
tenentInfo[0].tenentName || ""
);
}
localStorage.setItem(
"PageLanding",
element.pageId
);
localStorage.setItem(
"defaultmenuid",
element.menuId
);
localStorage.setItem(
"pageType",
element.pageType
);
setState({ ...state, loading: false });
if (isEnableSubscription) {
const LocalUserDetails = {
name: results[0].get("Name"),
email: results[0].get("Email"),
phone: results[0]?.get("Phone") || "",
company: results[0].get("Company")
localStorage.setItem("showpopup", true);
localStorage.setItem(
"PageLanding",
element.pageId
);
localStorage.setItem(
"defaultmenuid",
element.menuId
);
localStorage.setItem(
"pageType",
element.pageType
);
setState({ ...state, loading: false });
navigate("/");
} else {
extendedInfo.forEach((x) => {
if (x.TenantId) {
let obj = {
tenentId: x.TenantId.objectId,
tenentName:
x.TenantId.TenantName || ""
};
localStorage.setItem(
"userDetails",
JSON.stringify(LocalUserDetails)
"TenantId",
x.TenantId.objectId
);
const res = await fetchSubscription();
const freeplan = res.plan;
const billingDate = res.billingDate;
if (freeplan === "freeplan") {
navigate(redirectUrl);
} else if (billingDate) {
if (
new Date(billingDate) > new Date()
) {
localStorage.removeItem(
"userDetails"
);
// Redirect to the appropriate URL after successful login
navigate(redirectUrl);
} else {
navigate(`/subscription`, {
replace: true
});
}
} else {
navigate(`/subscription`, {
replace: true
});
}
} else {
// Redirect to the appropriate URL after successful login
navigate(redirectUrl);
tenentInfo.push(obj);
}
});
if (tenentInfo.length) {
dispatch(
showTenant(
tenentInfo[0].tenentName || ""
)
);
localStorage.setItem(
"TenantName",
tenentInfo[0].tenentName || ""
);
}
} else {
localStorage.setItem(
"PageLanding",
element.pageId
@@ -312,17 +234,35 @@ function Login() {
setState({ ...state, loading: false });
if (isEnableSubscription) {
const LocalUserDetails = {
name: _user.name,
email: email,
phone: _user?.phone || ""
// company: results.get("Company"),
name: results[0].get("Name"),
email: results[0].get("Email"),
phone: results[0]?.get("Phone") || "",
company: results[0].get("Company")
};
localStorage.setItem(
"userDetails",
JSON.stringify(LocalUserDetails)
);
const billingDate = "";
if (billingDate) {
const res = await fetchSubscription();
const freeplan = res.plan;
const billingDate = res.billingDate;
if (freeplan === "freeplan") {
navigate(redirectUrl);
} else if (billingDate) {
if (
new Date(billingDate) > new Date()
) {
localStorage.removeItem(
"userDetails"
);
// Redirect to the appropriate URL after successful login
navigate(redirectUrl);
} else {
navigate(`/subscription`, {
replace: true
});
}
} else {
navigate(`/subscription`, {
replace: true
});
@@ -332,28 +272,56 @@ function Login() {
navigate(redirectUrl);
}
}
},
(error) => {
const payload = {
sessionToken: user.getSessionToken()
};
handleSubmitbtn(payload);
console.error(
"Error while fetching Follow",
error
} else {
localStorage.setItem(
"PageLanding",
element.pageId
);
localStorage.setItem(
"defaultmenuid",
element.menuId
);
localStorage.setItem(
"pageType",
element.pageType
);
setState({ ...state, loading: false });
if (isEnableSubscription) {
const LocalUserDetails = {
name: _user.name,
email: email,
phone: _user?.phone || ""
// company: results.get("Company"),
};
localStorage.setItem(
"userDetails",
JSON.stringify(LocalUserDetails)
);
const billingDate = "";
if (billingDate) {
navigate(`/subscription`, {
replace: true
});
}
} else {
// Redirect to the appropriate URL after successful login
navigate(redirectUrl);
}
}
);
}
});
} else {
setState({ ...state, loading: false });
setIsModal(true);
}
} else {
setState({ ...state, loading: false });
setIsModal(true);
}
}
});
} else {
setState({ ...state, loading: false });
setIsModal(true);
}
})
.catch((error) => {
const payload = {
sessionToken: user.getSessionToken()
};
handleSubmitbtn(payload);
console.error("Error while fetching Follow", error);
});
})
.catch((err) => {
console.log("err", err);
@@ -474,7 +442,7 @@ function Login() {
let _currentRole = "";
const valuesToExclude = [
"contracts_Guest",
`${localStorage.getItem("_appName")}_appeditor`
"contracts_appeditor"
];
if (userRoles.length > 1) {
const rolesfiltered = userRoles.filter(
@@ -493,20 +461,13 @@ function Login() {
_currentRole = "";
}
}
if (
_currentRole &&
_currentRole !==
`${localStorage.getItem("_appName")}_appeditor`
) {
if (_currentRole && _currentRole !== "contracts_appeditor") {
userSettings.forEach(async (element) => {
const redirectUrl =
location?.state?.from ||
`/${element.pageType}/${element.pageId}`;
if (element.role === _currentRole) {
let _role = _currentRole.replace(
`${localStorage.getItem("_appName")}_`,
""
);
let _role = _currentRole.replace("contracts_", "");
localStorage.setItem("_user_role", _role);
// Get TenentID from Extendend Class
@@ -767,10 +728,7 @@ function Login() {
userRoles = roles;
let _currentRole = "";
if (userRoles.length > 1) {
if (
userRoles[0] ===
`${localStorage.getItem("_appName")}_appeditor`
) {
if (userRoles[0] === "contracts_appeditor") {
_currentRole = userRoles[1];
} else {
const rolesfiltered = userRoles.filter(
+1 -1
View File
@@ -265,7 +265,7 @@ const ManageSign = () => {
<div className="relative">
<div>
{image ? (
<div className="signatureCanvas relative border-[2px] border-[#888] rounded-box">
<div className="signatureCanvas relative border-[2px] border-[#888] rounded-box overflow-hidden">
<img
alt="signature"
src={image}
+278
View File
@@ -0,0 +1,278 @@
import React, { useEffect, useState } from "react";
import Parse from "parse";
import Alert from "../primitives/Alert";
import Loader from "../primitives/Loader";
import { useLocation, useNavigate } from "react-router-dom";
import ModalUi from "../primitives/ModalUi";
import pad from "../assets/images/pad.svg";
import Tooltip from "../primitives/Tooltip";
import AddSigner from "../components/AddSigner";
import AddUser from "../components/AddUser";
const heading = ["Sr.No", "Name", "Email", "Phone", "Departments"];
const actions = [];
const UserList = () => {
const [userList, setUserList] = useState([]);
const [isLoader, setIsLoader] = useState(false);
const [isModal, setIsModal] = useState(false);
const navigate = useNavigate();
const location = useLocation();
const isDashboard =
location?.pathname === "/dashboard/35KBoSgoAK" ? true : false;
const [currentPage, setCurrentPage] = useState(1);
const [isAlert, setIsAlert] = useState({ type: "success", msg: "" });
const [isDeleteModal, setIsDeleteModal] = useState(false);
const recordperPage = 10;
const startIndex = (currentPage - 1) * recordperPage; // user per page
const getPaginationRange = () => {
const totalPageNumbers = 7; // Adjust this value to show more/less page numbers
const pages = [];
const totalPages = Math.ceil(userList.length / recordperPage);
if (totalPages <= totalPageNumbers) {
for (let i = 1; i <= totalPages; i++) {
pages.push(i);
}
} else {
const leftSiblingIndex = Math.max(currentPage - 1, 1);
const rightSiblingIndex = Math.min(currentPage + 1, totalPages);
const showLeftDots = leftSiblingIndex > 2;
const showRightDots = rightSiblingIndex < totalPages - 2;
const firstPageIndex = 1;
const lastPageIndex = totalPages;
if (!showLeftDots && showRightDots) {
let leftItemCount = 3;
let leftRange = Array.from({ length: leftItemCount }, (_, i) => i + 1);
pages.push(...leftRange);
pages.push("...");
pages.push(totalPages);
} else if (showLeftDots && !showRightDots) {
let rightItemCount = 3;
let rightRange = Array.from(
{ length: rightItemCount },
(_, i) => totalPages - rightItemCount + i + 1
);
pages.push(firstPageIndex);
pages.push("...");
pages.push(...rightRange);
} else if (showLeftDots && showRightDots) {
let middleRange = Array.from(
{ length: 3 },
(_, i) => leftSiblingIndex + i
);
pages.push(firstPageIndex);
pages.push("...");
pages.push(...middleRange);
pages.push("...");
pages.push(lastPageIndex);
}
}
return pages;
};
const pageNumbers = getPaginationRange();
useEffect(() => {
fetchUserList();
}, []);
async function fetchUserList() {
try {
setIsLoader(true);
const organization = JSON.parse(localStorage.getItem("Extand_Class"));
const res = await Parse.Cloud.run("getuserlist", {
organizationId: organization[0].objectId
});
console.log("res ", res);
const _userRes = JSON.parse(JSON.stringify(res));
setUserList(_userRes);
} catch (err) {
console.log("Err ", err);
} finally {
setIsLoader(false);
}
}
const handleFormModal = () => {
setIsModal(!isModal);
};
const handleDelete = () => {};
const handleClose = () => {};
// Change page
const paginateFront = () => setCurrentPage(currentPage + 1);
const paginateBack = () => setCurrentPage(currentPage - 1);
const handleActionBtn = () => {};
const handleUserData = (userData) => {
console.log("userData", userData);
};
return (
<div className="relative">
{isLoader && (
<div className="absolute w-full h-full flex justify-center items-center bg-black bg-opacity-30 z-30">
<Loader />
</div>
)}
<div className="p-2 w-full bg-base-100 text-base-content op-card shadow-lg">
{isAlert && <Alert type={isAlert.type}>{isAlert.msg}</Alert>}
<div className="flex flex-row items-center justify-between my-2 mx-3 text-[20px] md:text-[23px]">
<div className="font-light">
User list{" "}
<span className="text-xs md:text-[13px] font-normal">
<Tooltip message={"user list from departments"} />
</span>
</div>
<div className="cursor-pointer" onClick={() => handleFormModal()}>
<i className="fa-light fa-square-plus text-accent text-[40px]"></i>
</div>
</div>
<div className={` overflow-x-auto w-full`}>
<table className="op-table border-collapse w-full">
<thead className="text-[14px]">
<tr className="border-y-[1px]">
{heading?.map((item, index) => (
<React.Fragment key={index}>
<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]">
{userList?.length > 0 && (
<>
{userList.map((item, index) => (
<tr className="border-y-[1px]" key={index}>
{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-4 py-2 ">{item?.Email || "-"}</td>
<td className="px-4 py-2">{item?.Phone || "-"}</td>
<td className="px-3 py-2 text-white grid grid-cols-2">
{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`}
>
<i className={act.btnIcon}></i>
</button>
))}
{isDeleteModal[item.objectId] && (
<ModalUi
isOpen
title={"Delete Contact"}
handleClose={handleClose}
>
<div className="m-[20px]">
<div className="text-lg font-normal text-black">
Are you sure you want to delete this contact?
</div>
<hr className="bg-[#ccc] mt-4 " />
<div className="flex items-center mt-3 gap-2 text-white">
<button
onClick={() => handleDelete(item)}
className="op-btn op-btn-primary"
>
Yes
</button>
<button
onClick={handleClose}
className="op-btn op-btn-secondary"
>
No
</button>
</div>
</div>
</ModalUi>
)}
</td>
</tr>
))}
</>
)}
</tbody>
</table>
</div>
<div className="op-join flex flex-wrap items-center p-2">
{userList.length > recordperPage && (
<button
onClick={() => paginateBack()}
className="op-join-item op-btn op-btn-sm"
>
Prev
</button>
)}
{pageNumbers.map((x, i) => (
<button
key={i}
onClick={() => setCurrentPage(x)}
disabled={x === "..."}
className={`${
x === currentPage ? "op-btn-active" : ""
} op-join-item op-btn op-btn-sm`}
>
{x}
</button>
))}
{userList.length > recordperPage && (
<button
onClick={() => paginateFront()}
className="op-join-item op-btn op-btn-sm"
>
Next
</button>
)}
</div>
{userList?.length <= 0 && (
<div
className={`${
isDashboard ? "h-[317px]" : ""
} flex flex-col items-center justify-center w-ful bg-base-100 text-base-content rounded-xl py-4`}
>
<div className="w-[60px] h-[60px] overflow-hidden">
<img
className="w-full h-full object-contain"
src={pad}
alt="img"
/>
</div>
<div className="text-sm font-semibold">No Data Available</div>
</div>
)}
<ModalUi
title={"Add User"}
isOpen={isModal}
handleClose={handleFormModal}
>
{/* <AddSigner
handleUserData={handleUserData}
closePopup={handleFormModal}
/> */}
<AddUser
handleUserData={handleUserData}
closePopup={handleFormModal}
/>
</ModalUi>
</div>
</div>
);
};
export default UserList;
+2 -2
View File
@@ -143,13 +143,13 @@ export const updateMailCount = async extUserId => {
await contractUser.save(null, { useMasterKey: true });
} else {
// Create new entry if not found
const ContractsUsers = Parse.Object.extend('contracts_users');
const ContractsUsers = Parse.Object.extend('contracts_Users');
const newContractUser = new ContractsUsers();
newContractUser.set('EmailCount', 1);
await newContractUser.save(null, { useMasterKey: true });
}
} catch (error) {
console.log('Error updating EmailCount in contracts_users: ' + error.message);
console.log('Error updating EmailCount in contracts_Users: ' + error.message);
}
};
+4
View File
@@ -44,6 +44,8 @@ import GetPublicUserName from './parsefunction/GetPublicUserName.js';
import GetPublicTemplate from './parsefunction/GetPublicTemplate.js';
import ssoSignin from './parsefunction/ssoSignin.js';
import isextenduser from './parsefunction/isextenduser.js';
import getUserByOrgId from './parsefunction/getuserbyOrgId.js';
import getUserList from './parsefunction/getUserList.js';
// This afterSave function triggers after an object is added or updated in the specified class, allowing for post-processing logic.
Parse.Cloud.afterSave('contracts_Document', DocumentAftersave);
@@ -98,3 +100,5 @@ Parse.Cloud.define('getpublicusername', GetPublicUserName);
Parse.Cloud.define('getpublictemplate', GetPublicTemplate);
Parse.Cloud.define('ssosign', ssoSignin);
Parse.Cloud.define('isextenduser', isextenduser);
Parse.Cloud.define('getuserbyorgid', getUserByOrgId);
Parse.Cloud.define('getuserlist', getUserList);
@@ -17,13 +17,13 @@ async function DocumentBeforesave(request) {
await contractUser.save(null, { useMasterKey: true });
} else {
// Create new entry if not found
const ContractsUsers = Parse.Object.extend('contracts_users');
const ContractsUsers = Parse.Object.extend('contracts_Users');
const newContractUser = new ContractsUsers();
newContractUser.set('DocumentCount', 1);
await newContractUser.save(null, { useMasterKey: true });
}
} catch (error) {
console.log('Error updating document count in contracts_users: ' + error.message);
console.log('Error updating document count in contracts_Users: ' + error.message);
}
if (document?.get('Signers') && document.get('Signers').length > 0) {
document.set('DocSentAt', new Date());
@@ -15,13 +15,13 @@ async function TemplateBeforeSave(request) {
await contractUser.save(null, { useMasterKey: true });
} else {
// Create new entry if not found
const ContractsUsers = Parse.Object.extend('contracts_users');
const ContractsUsers = Parse.Object.extend('contracts_Users');
const newContractUser = new ContractsUsers();
newContractUser.set('TemplateCount', 1);
await newContractUser.save(null, { useMasterKey: true });
}
} catch (error) {
console.log('Error updating template count in contracts_users: ' + error.message);
console.log('Error updating template count in contracts_Users: ' + error.message);
}
}
} catch (err) {
@@ -0,0 +1,26 @@
export default async function getUserByOrgId(req) {
const OrganizationId = req.params.organizationId;
const orgPtr = {
__type: 'Pointer',
className: 'contracts_Organizations',
objectId: OrganizationId,
};
if (!req?.user) {
throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'User is not authenticated.');
} else {
try {
const extUser = new Parse.Query('contracts_Users');
extUser.equalTo('OrganizationId', orgPtr);
const userRes = await extUser.first({ useMasterKey: true });
if (userRes.length > 0) {
const _userRes = JSON.parse(JSON.stringify(userRes));
return _userRes;
} else {
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'User not found.');
}
} catch (err) {
console.log('err in getuserlist', err);
throw err;
}
}
}
@@ -0,0 +1,26 @@
export default async function getUserList(req) {
const OrganizationId = req.params.organizationId;
const orgPtr = {
__type: 'Pointer',
className: 'contracts_Organizations',
objectId: OrganizationId,
};
if (!req?.user) {
throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'User is not authenticated.');
} else {
try {
const extUser = new Parse.Query('contracts_Users');
extUser.equalTo('OrganizationId', orgPtr);
const userRes = await extUser.find({ useMasterKey: true });
if (userRes.length > 0) {
const _userRes = JSON.parse(JSON.stringify(userRes));
return _userRes;
} else {
return [];
}
} catch (err) {
console.log('err in getuserlist', err);
throw err;
}
}
}
@@ -18,8 +18,7 @@ export default async function getapitoken(request) {
}
}
} catch (err) {
console.log('Err', err);
console.log('err', err);
console.log('Err in getapitoken', err);
if (err.code == 209) {
return { error: 'Invalid session token' };
} else {