Merge pull request #311 from OpenSignLabs/opensign-drive

feat: implement of document delete and move to folder in opensigndrive
This commit is contained in:
prafull-opensignlabs
2024-01-10 18:29:32 +05:30
committed by GitHub
19 changed files with 817 additions and 684 deletions
+2 -4
View File
@@ -2211,7 +2211,5 @@
background-position: -2em 0;
}
}
.box:nth-of-type(n + 43) {
display: none;
}
@@ -21,6 +21,7 @@ export default async function getDocument(request) {
query.include('Signers');
query.include('AuditTrail.UserPtr');
query.include('Placeholders');
query.notEqualTo('IsArchive', true)
const res = await query.first({ useMasterKey: true });
if (res) {
const acl = res.getACL();
@@ -16,9 +16,9 @@ export default async function getDrive(request) {
if (userId) {
let url;
if (docId) {
url = `${classUrl}?where={"Folder":{"__type":"Pointer","className":"contracts_Document","objectId":"${docId}"},"CreatedBy":{"__type":"Pointer","className":"_User","objectId":"${userId}"}}&include=ExtUserPtr,Signers,Folder`;
url = `${classUrl}?where={"Folder":{"__type":"Pointer","className":"contracts_Document","objectId":"${docId}"},"CreatedBy":{"__type":"Pointer","className":"_User","objectId":"${userId}"},"IsArchive":{"$ne":true}}&include=ExtUserPtr,Signers,Folder`;
} else {
url = `${classUrl}?where={"Folder":{"$exists":false},"CreatedBy":{"__type":"Pointer","className":"_User","objectId":"${userId}"}}&include=ExtUserPtr,Signers`;
url = `${classUrl}?where={"Folder":{"$exists":false},"CreatedBy":{"__type":"Pointer","className":"_User","objectId":"${userId}"},"IsArchive":{"$ne":true}}&include=ExtUserPtr,Signers`;
}
try {
const res = await axios.get(url, {
@@ -7,11 +7,11 @@ export default function reportJson(id, userId) {
return {
reportName: 'Draft Documents',
params: {
Type: null,
$or: [
{ Signers: null, SignedUrl: null },
{ Signers: { $exists: true }, Placeholders: null },
],
Type: { $ne: 'Folder' },
IsCompleted: { $ne: true },
IsDeclined: { $ne: true },
IsArchive: { $ne: true },
$or: [{ Signers: null }, { Signers: { $exists: true }, Placeholders: null }],
CreatedBy: {
__type: 'Pointer',
className: '_User',
@@ -28,6 +28,7 @@ export default function reportJson(id, userId) {
Type: { $ne: 'Folder' },
IsCompleted: { $ne: true },
IsDeclined: { $ne: true },
IsArchive: { $ne: true },
ExpiryDate: {
$gt: { __type: 'Date', iso: new Date().toISOString() },
},
@@ -66,6 +67,7 @@ export default function reportJson(id, userId) {
Placeholders: { $ne: null },
IsCompleted: { $ne: true },
IsDeclined: { $ne: true },
IsArchive: { $ne: true },
CreatedBy: {
__type: 'Pointer',
className: '_User',
@@ -82,7 +84,7 @@ export default function reportJson(id, userId) {
return {
reportName: 'Completed Documents',
params: {
Type: null,
Type: { $ne: 'Folder' },
IsCompleted: true,
CreatedBy: {
__type: 'Pointer',
@@ -90,6 +92,7 @@ export default function reportJson(id, userId) {
objectId: currentUserId,
},
IsDeclined: { $ne: true },
IsArchive: { $ne: true },
},
keys: [
'Name',
@@ -108,6 +111,7 @@ export default function reportJson(id, userId) {
reportName: 'Declined Documents',
params: {
Type: null,
IsArchive: { $ne: true },
IsDeclined: true,
CreatedBy: {
__type: 'Pointer',
@@ -125,6 +129,7 @@ export default function reportJson(id, userId) {
params: {
IsCompleted: { $ne: true },
IsDeclined: { $ne: true },
IsArchive: { $ne: true },
Type: { $ne: 'Folder' },
$and: [
{
@@ -157,6 +162,7 @@ export default function reportJson(id, userId) {
Placeholders: { $ne: null },
IsCompleted: { $ne: true },
IsDeclined: { $ne: true },
IsArchive: { $ne: true },
CreatedBy: {
__type: 'Pointer',
className: '_User',
@@ -176,6 +182,7 @@ export default function reportJson(id, userId) {
Type: { $ne: 'Folder' },
IsCompleted: { $ne: true },
IsDeclined: { $ne: true },
IsArchive: { $ne: true },
ExpiryDate: {
$gt: { __type: 'Date', iso: new Date().toISOString() },
},
@@ -200,11 +207,11 @@ export default function reportJson(id, userId) {
return {
reportName: 'Drafts',
params: {
Type: null,
$or: [
{ Signers: null, SignedUrl: null },
{ Signers: { $exists: true }, Placeholders: null },
],
Type: { $ne: 'Folder' },
IsCompleted: { $ne: true },
IsDeclined: { $ne: true },
IsArchive: { $ne: true },
$or: [{ Signers: null }, { Signers: { $exists: true }, Placeholders: null }],
CreatedBy: {
__type: 'Pointer',
className: '_User',
@@ -235,6 +242,7 @@ export default function reportJson(id, userId) {
reportClass: 'contracts_Template',
params: {
Type: { $ne: 'Folder' },
IsArchive: { $ne: true },
CreatedBy: {
__type: 'Pointer',
className: '_User',
@@ -59,7 +59,7 @@ exports.up = async Parse => {
},
{
icon: 'fas fa-folder',
title: 'OpenSignDrive',
title: 'OpenSignDrive',
target: '_self',
pageType: 'mf',
description: '',
@@ -206,6 +206,15 @@ exports.up = async Parse => {
description: '',
objectId: '6TeaPr321t',
},
{
icon: 'fas fa-folder',
title: 'OpenSign™ Drive',
target: '_self',
pageType: 'mf',
description: '',
objectId:
'remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/legadrive',
},
{
icon: 'fas fa-address-card',
title: 'Reports',
@@ -576,4 +585,4 @@ exports.down = async Parse => {
// schema.addString('name').addNumber('cash');
const batch = [revertUserMenu, revertAdminMenu];
return Parse.Object.saveAll(batch, { useMasterKey: true });
};
};
@@ -0,0 +1,23 @@
/**
*
* @param {Parse} Parse
*/
exports.up = async Parse => {
// TODO: set className here
const className = 'contracts_Document';
const schema = new Parse.Schema(className);
schema.addBoolean('IsArchive');
return schema.update();
};
/**
*
* @param {Parse} Parse
*/
exports.down = async Parse => {
// TODO: set className here
const className = 'contracts_Document';
const schema = new Parse.Schema(className);
schema.deleteField('IsArchive');
return schema.update();
};
@@ -47,65 +47,34 @@ function DraftDocument() {
//check document type and render on signyour self and placeholder route
const handleDraftDoc = () => {
const data = pdfDetails[0];
const checkSignerExist =
pdfDetails[0] && pdfDetails[0].Signers && pdfDetails[0].Signers;
const isPlaceholder =
pdfDetails[0].Placeholders && pdfDetails[0].Placeholders;
const isDecline = data.IsDeclined && data.IsDeclined;
const signUrl = data.SignedUrl && data.SignedUrl;
const expireDate =
pdfDetails[0] &&
pdfDetails[0].ExpiryDate.iso &&
pdfDetails[0].ExpiryDate.iso;
const expireUpdateDate = new Date(expireDate).getTime();
const currDate = new Date().getTime();
const hostUrl = getHostUrl();
const signerExist = data.Signers && data.Signers;
const isDecline = data.IsDeclined && data.IsDeclined;
const isPlaceholder = data.Placeholders && data.Placeholders;
//checking document is completed and signer exist then navigate to pdfRequestFiles file
if (data.IsCompleted && checkSignerExist) {
navigate(`${hostUrl}pdfRequestFiles`);
//checking if document has completed and request signature flow
if (data?.IsCompleted && signerExist?.length > 0) {
navigate(`${hostUrl}pdfRequestFiles/${data.objectId}`);
}
//checking document is completed and signer does not exist then navigate to recipientSignPdf file
else if (data.IsCompleted && !checkSignerExist) {
navigate(`${hostUrl}signaturePdf`);
//checking if document has completed and signyour-self flow
else if (!signerExist && !isPlaceholder) {
navigate(`${hostUrl}signaturePdf/${data.objectId}`);
}
//checking document is declined by someone then navigate to pdfRequestFiles file
//checking if document has declined by someone
else if (isDecline) {
navigate(`${hostUrl}pdfRequestFiles`);
navigate(`${hostUrl}pdfRequestFiles/${data.objectId}`);
//checking draft type document
}
//checking document has expired and signers exist and placeholder does not set yet then navigate to pdfRequestFiles file
//draft type request sign document
//Inprogress document
else if (isPlaceholder?.length > 0 && signerExist?.length > 0) {
navigate(`${hostUrl}pdfRequestFiles/${data.objectId}`);
} //placeholder draft document
else if (
currDate > expireUpdateDate &&
checkSignerExist &&
!isPlaceholder
(signerExist?.length > 0 &&
(!isPlaceholder || isPlaceholder?.length === 0)) ||
((!signerExist || signerExist?.length === 0) && isPlaceholder?.length > 0)
) {
navigate(`${hostUrl}placeHolderSign`);
}
//checking document has expired and signers does not exist and document not signed yet then navigate to pdfRequestFiles file
//draft type signyouselfdocument
else if (
currDate > expireUpdateDate &&
!checkSignerExist &&
!isPlaceholder &&
!signUrl
) {
// window.location.hash = `/signaturePdf`;
navigate(`${hostUrl}signaturePdf`);
}
//checking document has expired and signers exist and document then navigate to pdfRequestFiles file
else if (currDate > expireUpdateDate) {
// window.location.hash = `/pdfRequestFiles`;
navigate(`${hostUrl}pdfRequestFiles`);
}
//checking document has expired not been expired yet and signers exist and placeholder does not set yet then navigate to pdfRequestFiles file
//draft type request sign document
else if (!signUrl && checkSignerExist) {
navigate(`${hostUrl}placeHolderSign`);
// window.location.hash = `/placeHolderSign`;
} else {
// window.location.hash = `/signaturePdf/`;
navigate(`${hostUrl}signaturePdf`);
navigate(`${hostUrl}placeHolderSign/${data.objectId}`);
}
};
@@ -10,6 +10,9 @@ import { getHostUrl } from "../../../utils/Utils";
import { useNavigate } from "react-router-dom";
import Table from "react-bootstrap/Table";
import * as HoverCard from "@radix-ui/react-hover-card";
import SelectFolder from "../../../premitives/SelectFolder";
import ModalUi from "../../../premitives/ModalUi";
import { themeColor } from "../../../utils/ThemeColor/backColor";
function PdfFileComponent({
pdfData,
@@ -22,7 +25,15 @@ function PdfFileComponent({
const [rename, setRename] = useState("");
const [renameValue, setRenameValue] = useState("");
const inputRef = useRef(null);
const [isOpenMoveModal, setIsOpenMoveModal] = useState(false);
const [selectDoc, setSelectDoc] = useState();
const [isDeleteDoc, setIsDeleteDoc] = useState(false);
const contextMenu = [
{ type: "Download", icon: "fa-solid fa-arrow-down" },
{ type: "Rename", icon: "fa-solid fa-font" },
{ type: "Move", icon: "fa-solid fa-file-export" },
{ type: "Delete", icon: "fa-solid fa-trash" }
];
const navigate = useNavigate();
//to focus input box on press rename to change doc name
@@ -100,74 +111,175 @@ function PdfFileComponent({
//function for navigate user to microapp-signature component
const checkPdfStatus = async (data) => {
const hostUrl = getHostUrl();
const expireDate = data.ExpiryDate.iso;
const expireUpdateDate = new Date(expireDate).getTime();
const currDate = new Date().getTime();
const signerExist = data.Signers && data.Signers;
const signUrl = data.SignedUrl && data.SignedUrl;
const isDecline = data.IsDeclined && data.IsDeclined;
const isPlaceholder = data.Placeholders && data.Placeholders;
//checking and navigate to signyouself page
const checkPlaceHolder = data.Placeholders;
//checking if document has completed
if (data.IsCompleted && signerExist) {
navigate(`${hostUrl}pdfRequestFiles/${data.objectId}`);
// window.location.hash = `/pdfRequestFiles/${data.objectId}`;
} else if (data.IsCompleted && !signerExist) {
//checking if document has completed and request signature flow
if (data?.IsCompleted && signerExist?.length > 0) {
navigate(`${hostUrl}pdfRequestFiles/${data.objectId}`);
}
//checking if document has completed and signyour-self flow
else if (!signerExist && !isPlaceholder) {
navigate(`${hostUrl}signaturePdf/${data.objectId}`);
}
//checking if document has declined by someone
else if (isDecline) {
navigate(`${hostUrl}pdfRequestFiles/${data.objectId}`);
// window.location.hash = `/pdfRequestFiles/${data.objectId}`;
} else if (currDate > expireUpdateDate && signerExist && !isPlaceholder) {
// window.location.hash = `/placeHolderSign/${data.objectId}`;
navigate(`${hostUrl}placeHolderSign/${data.objectId}`);
} else if (
currDate > expireUpdateDate &&
!signerExist &&
!isPlaceholder &&
!signUrl
) {
navigate(`${hostUrl}signaturePdf/${data.objectId}`);
// window.location.hash = `/signaturePdf/${data.objectId}`;
//checking draft type document
}
//checking if document has expired
else if (currDate > expireUpdateDate) {
//Inprogress document
else if (isPlaceholder?.length > 0 && signerExist?.length > 0) {
navigate(`${hostUrl}pdfRequestFiles/${data.objectId}`);
// window.location.hash = `/pdfRequestFiles/${data.objectId}`;
} //checking if document is draft signers type and signers placeholder does not placed yet
else if (!signUrl && signerExist) {
// window.location.hash = `/placeHolderSign/${data.objectId}`;
navigate(`${hostUrl}placeHolderSign/${data.objectId}`);
}
//checking if document is request type and signers placeholder exist and does not completed yet
//then user can check progress of document and sign also
} //placeholder draft document
else if (
checkPlaceHolder &&
checkPlaceHolder.length > 0 &&
!data.IsCompleted
(signerExist?.length > 0 &&
(!isPlaceholder || isPlaceholder?.length === 0)) ||
((!signerExist || signerExist?.length === 0) && isPlaceholder?.length > 0)
) {
navigate(`${hostUrl}pdfRequestFiles/${data.objectId}`);
// window.location.hash = `/pdfRequestFiles/${data.objectId}`;
navigate(`${hostUrl}placeHolderSign/${data.objectId}`);
}
//checking document is draft and signyourself type then user can sign document
else {
navigate(`${hostUrl}signaturePdf/${data.objectId}`);
// navigate(`/signaturePdf/${data.objectId}`);
// window.location.hash = `/signaturePdf/${data.objectId}`;
};
const handleMenuItemClick = (selectType, data) => {
switch (selectType) {
case "Download":
const pdfName = data && data.Name;
const pdfUrl = data && data.SignedUrl ? data.SignedUrl : data.URL;
saveAs(pdfUrl, `${sanitizeFileName(pdfName)}_signed_by_OpenSign™.pdf`);
break;
case "Rename":
setRenameValue(data.Name);
setRename(data.objectId);
break;
case "Delete":
setIsDeleteDoc(true);
setSelectDoc(data);
break;
case "Move":
handleMoveDocument(data);
break;
}
};
//function for delete document
const handleDeleteDocument = async (docData) => {
setIsDeleteDoc(false);
const docId = docData.objectId;
const data = {
IsArchive: true
};
await axios
.put(
`${localStorage.getItem("baseUrl")}classes/${localStorage.getItem(
"_appName"
)}_Document/${docId}`,
data,
{
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
}
}
)
.then((result) => {
const res = result.data;
const updatedData = pdfData.filter((x) => x.objectId !== docId);
setPdfData(updatedData);
})
.catch((err) => {
console.log("err", err);
});
};
const handleMoveDocument = async (docData) => {
setIsOpenMoveModal(true);
setSelectDoc(docData);
};
//function for move document from one folder to another folder
const handleMoveFolder = async (selectFolderData) => {
const selecFolderId = selectDoc?.Folder?.objectId;
const moveFolderId = selectFolderData?.ObjectId;
let updateDocId = selectDoc?.objectId;
let updateData;
const checkExist = moveFolderId
? selecFolderId === moveFolderId
? true
: false
: selecFolderId
? false
: true;
if (!checkExist) {
if (moveFolderId) {
updateData = {
Folder: {
__type: "Pointer",
className: `${localStorage.getItem("_appName")}_Document`,
objectId: moveFolderId
}
};
} else {
updateData = {
Folder: { __op: "Delete" }
};
}
await axios
.put(
`${localStorage.getItem("baseUrl")}classes/${localStorage.getItem(
"_appName"
)}_Document/${updateDocId}`,
updateData,
{
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
}
}
)
.then((Listdata) => {
// console.log("Listdata ", Listdata);
const json = Listdata.data;
const updatedData = pdfData.filter((x) => x.objectId !== updateDocId);
setPdfData(updatedData);
})
.catch((err) => {
console.log("err", err);
});
setIsOpenMoveModal(false);
} else {
alert("folder already exist!");
setIsOpenMoveModal(false);
}
};
const sanitizeFileName = (pdfName) => {
// Replace spaces with underscore
return pdfName.replace(/ /g, "_");
};
const handleEnterPress = (e, data) => {
if (e.key === "Enter") {
handledRenameDoc(data);
}
};
const handleDraftDoc = (data) => {
window.location.hash = `/mf/remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9MZWdhR2VuaWUtTWljcm9hcHBWMi9yZW1vdGVFbnRyeS5qcw==&moduleToLoad=AppRoutes&remoteName=legageniemicroapp/legagenie?${data.objectId}`;
};
//component to handle type of document and render according to type
const handleFolderData = (data, ind, listType) => {
// console.log("data", data);
let createddate,
status,
isDecline,
signerExist,
isExpire,
isComplete,
signUrl,
isPlaceholder;
@@ -182,64 +294,48 @@ function PdfFileComponent({
signUrl = data.SignedUrl && data.SignedUrl;
const expireUpdateDate = new Date(expireDate).getTime();
const currDate = new Date().getTime();
let isExpire = false;
if (currDate > expireUpdateDate) {
isExpire = true;
} else {
isExpire = false;
}
if (isComplete) {
status = "Completed";
} else if (isDecline) {
status = "Declined";
} else if (isExpire && !isPlaceholder && signerExist) {
// status = "Expired";
} else if (!signerExist || signerExist?.length === 0) {
status = "Draft";
} else if (isExpire && !isPlaceholder && !signerExist && !signUrl) {
// status = "Expired";
} else if (
signerExist?.length > 0 &&
(!isPlaceholder || isPlaceholder?.length === 0)
) {
status = "Draft";
} else if (isExpire) {
status = "Expired";
} else if (!signUrl) {
status = "Draft";
} else {
status = "InComplete";
status = "In Progress";
}
}
const handleDraftDoc = (data) => {
window.location.hash = `/mf/remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9MZWdhR2VuaWUtTWljcm9hcHBWMi9yZW1vdGVFbnRyeS5qcw==&moduleToLoad=AppRoutes&remoteName=legageniemicroapp/legagenie?${data.objectId}`;
};
const signersName = () => {
const getSignersName = signerExist.map((data) => data.Name);
const signerName = getSignersName.join(",");
const handleMenuItemClick = (selectType, data) => {
// console.log("data",data)
if (selectType === "Download") {
// console.log("download")
const pdfName = data && data.Name;
const pdfUrl = data && data.SignedUrl ? data.SignedUrl : data.URL;
saveAs(pdfUrl, `${sanitizeFileName(pdfName)}_signed_by_OpenSign™.pdf`);
} else if (selectType === "Rename") {
// console.log("rename")
setRenameValue(data.Name);
setRename(data.objectId);
}
return (
<span
className="statusSpan"
style={{ width: "90%", wordWrap: "break-word" }}
>
{signerName}{" "}
</span>
);
};
const sanitizeFileName = (pdfName) => {
// Replace spaces with underscore
return pdfName.replace(/ /g, "_");
};
const handleEnterPress = (e, data) => {
if (e.key === "Enter") {
handledRenameDoc(data);
}
};
return listType === "table" ? (
data.Type === "Folder" ? (
<tr onClick={() => handleOnclikFolder(data)}>
<td>
<td
style={{ cursor: "pointer", display: "flex", alignItems: "center" }}
>
<i
className="fa fa-folder"
aria-hidden="true"
@@ -257,7 +353,9 @@ function PdfFileComponent({
</tr>
) : data.Type === "AIDoc" ? (
<tr onClick={() => handleDraftDoc(data)}>
<td>
<td
style={{ cursor: "pointer", display: "flex", alignItems: "center" }}
>
<i
className="fa fa-file-text"
style={{ color: "#0ea3ed", marginRight: "8px", fontSize: "26px" }}
@@ -274,7 +372,9 @@ function PdfFileComponent({
</tr>
) : (
<tr onClick={() => checkPdfStatus(data)}>
<td>
<td
style={{ cursor: "pointer", display: "flex", alignItems: "center" }}
>
<i
className="fa fa-file-pdf"
style={{ color: "#ed4d0e", marginRight: "8px", fontSize: "26px" }}
@@ -329,7 +429,6 @@ function PdfFileComponent({
}}
autoFocus={true}
type="text"
// onFocus={()=>console.log("focus")}
onBlur={() => handledRenameDoc(data)}
onKeyDown={(e) => handleEnterPress(e, data)}
ref={inputRef}
@@ -355,19 +454,12 @@ function PdfFileComponent({
sideOffset={5}
align="end"
>
{/* <ContextMenu.Item
onClick={() => handleMenuItemClick("Download", data)}
onSelect={(e) => console.log("event", e)}
className="ContextMenuItem"
>
Download
</ContextMenu.Item> */}
<ContextMenu.Item
onClick={() => handleMenuItemClick("Rename", data)}
className="ContextMenuItem"
>
Rename
<i class="fa-solid fa-font"></i>
<span style={{ marginLeft: "8px" }}>Rename</span>
</ContextMenu.Item>
</ContextMenu.Content>
</ContextMenu.Portal>
@@ -402,7 +494,6 @@ function PdfFileComponent({
}}
autoFocus={true}
type="text"
// onFocus={()=>console.log("focus")}
onBlur={() => handledRenameDoc(data)}
onKeyDown={(e) => handleEnterPress(e, data)}
ref={inputRef}
@@ -428,26 +519,19 @@ function PdfFileComponent({
sideOffset={5}
align="end"
>
{/* <ContextMenu.Item
onClick={() => handleMenuItemClick("Download", data)}
onSelect={(e) => console.log("event", e)}
className="ContextMenuItem"
>
Download
</ContextMenu.Item> */}
<ContextMenu.Item
onClick={() => handleMenuItemClick("Rename", data)}
className="ContextMenuItem"
>
Rename
<i class="fa-solid fa-font"></i>
<span style={{ marginLeft: "8px" }}>Rename</span>
</ContextMenu.Item>
</ContextMenu.Content>
</ContextMenu.Portal>
</ContextMenu.Root>
</div>
) : (
<HoverCard.Root>
<HoverCard.Root openDelay={0} closeDelay={100}>
<HoverCard.Trigger asChild>
<div>
<ContextMenu.Root>
@@ -504,7 +588,7 @@ function PdfFileComponent({
<i className="fa fa-file"></i>
</div>
) : (
status === "InComplete" && (
status === "In Progress" && (
<div className="status-badge in-progress">
<i className="fa fa-paper-plane"></i>
</div>
@@ -518,20 +602,18 @@ function PdfFileComponent({
sideOffset={5}
align="end"
>
<ContextMenu.Item
onClick={() => handleMenuItemClick("Download", data)}
onSelect={(e) => console.log("event", e)}
className="ContextMenuItem"
>
Download
</ContextMenu.Item>
<ContextMenu.Item
onClick={() => handleMenuItemClick("Rename", data)}
className="ContextMenuItem"
>
Rename
</ContextMenu.Item>
{contextMenu.map((menu, ind) => {
return (
<ContextMenu.Item
key={ind}
onClick={() => handleMenuItemClick(menu.type, data)}
className="ContextMenuItem"
>
<i class={menu.icon}></i>
<span style={{ marginLeft: "8px" }}>{menu.type}</span>
</ContextMenu.Item>
);
})}
</ContextMenu.Content>
</ContextMenu.Portal>
</ContextMenu.Root>
@@ -554,56 +636,113 @@ function PdfFileComponent({
{signerExist && (
<>
<strong style={{ fontSize: "13px" }}>Signers: </strong>
{signerExist.map((data, key) => {
return (
<React.Fragment key={key}>
<span className="statusSpan">{data.Name}, </span>
</React.Fragment>
);
})}
{/* <span className="statusSpan">kjefjjnejkfnkbjs bbfjkdsbjbfjkbjk kscbjkbjkb</span> */}
{signersName()}
</>
)}
<HoverCard.Arrow className="HoverCardArrow" />
</HoverCard.Content>
</HoverCard.Portal>
</HoverCard.Root>
);
};
//component to handle type of document and render according to type
return isList ? (
<div className="container" style={{ overflowX: "auto" }}>
<Table striped bordered hover>
<thead>
<tr>
<th>Name</th>
<th>Created Date</th>
<th>Type</th>
<th>Status</th>
<th>Action</th>
</tr>
</thead>
<tbody>
//component to handle type of document and render according to type
return (
<>
{isList ? (
<div className="container" style={{ overflowX: "auto" }}>
<Table striped bordered hover>
<thead>
<tr>
<th>Name</th>
<th>Created Date</th>
<th>Type</th>
<th>Status</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{pdfData.map((data, ind) => {
return (
<React.Fragment key={ind}>
{handleFolderData(data, ind, "table")}
</React.Fragment>
);
})}
</tbody>
</Table>
</div>
) : (
<div className="pdfContainer">
{pdfData.map((data, ind) => {
return (
<React.Fragment key={ind}>
{handleFolderData(data, ind, "table")}
</React.Fragment>
<div className="box" key={ind}>
{handleFolderData(data, ind, "list")}
</div>
);
})}
</tbody>
</Table>
</div>
) : (
<div className="pdfContainer">
{pdfData.map((data, ind) => {
return (
<div className="box" key={ind}>
{handleFolderData(data, ind, "list")}
</div>
);
})}
</div>
</div>
)}
{isOpenMoveModal && (
<SelectFolder
onSuccess={handleMoveFolder}
isOpenModal={isOpenMoveModal}
folderCls={"contracts_Document"}
setIsOpenMoveModal={setIsOpenMoveModal}
setPdfData={setPdfData}
/>
)}
<ModalUi
isOpen={isDeleteDoc}
headerColor={themeColor()}
title={"Delete Document"}
handleClose={() => {
setIsDeleteDoc(false);
}}
>
<div style={{ height: "100%", padding: 20 }}>
<p>Are you sure you want to delete this document?</p>
<div
style={{
height: "1px",
backgroundColor: "#9f9f9f",
width: "100%",
marginTop: "15px",
marginBottom: "15px"
}}
></div>
<button
onClick={() => {
handleDeleteDocument(selectDoc);
}}
style={{
background: themeColor(),
color: "white"
}}
type="button"
className="finishBtn"
>
Yes
</button>
<button
onClick={() => {
setIsDeleteDoc(false);
}}
style={{
color: "black"
}}
type="button"
className="finishBtn"
>
No
</button>
</div>
</ModalUi>
</>
);
}
@@ -6,12 +6,13 @@
.ContextMenuContent,
.ContextMenuSubContent {
min-width: 150px;
min-width: 135px;
background-color: white;
border-radius: 6px;
overflow: hidden;
padding: 5px;
box-shadow: 0px 10px 38px -10px rgba(22, 23, 24, 0.35), 0px 10px 20px -15px rgba(22, 23, 24, 0.2);
z-index: 99;
}
.ContextMenuItem,
@@ -27,7 +28,7 @@
height: 25px;
padding: 0 5px;
position: relative;
padding-left: 25px;
padding-left: 15px;
user-select: none;
outline: none;
}
@@ -395,6 +396,7 @@ a {
will-change: transform, opacity;
text-align: center;
align-items: center;
}
.HoverCardContent[data-side='top'] {
@@ -496,12 +498,34 @@ a {
/* for Chrome, Safari, and Opera */
}
.docDeleteBtn {
/* box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.18); */
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
padding: 7px 17px;
color: white;
font-weight: 600 !important;
font-size: 12px !important;
border: none;
border-radius: 2px;
}
.docDeleteBtn:focus {
border: none;
outline: none;
}
.docDeleteBtn:hover {
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1), 0 2px 4px rgba(0, 0, 0, 0.18);
color: white;
}
@media screen and (max-width:766px) {
.itemColor {
font-size: 10px !important;
}
}
@media (min-width: 310px) and (max-width:550px) {
.pdfContainer {
@@ -9,6 +9,9 @@ import { themeColor, iconColor } from "../../utils/ThemeColor/backColor";
import { getDrive } from "../../utils/Utils";
import AlertComponent from "../component/alertComponent";
import { useNavigate } from "react-router-dom";
import Title from "../component/Title";
import Parse from "parse";
import ModalUi from "../../premitives/ModalUi";
function PdfFile() {
const navigate = useNavigate();
@@ -27,7 +30,7 @@ function PdfFile() {
message: "This might take some time"
});
const [docId, setDocId] = useState();
const [handleError, setHandleError] = useState();
const [handleError, setHandleError] = useState("");
const [folderName, setFolderName] = useState([]);
const [isAlert, setIsAlert] = useState({ isShow: false, alertMessage: "" });
const [isNewFol, setIsNewFol] = useState(false);
@@ -54,15 +57,18 @@ function PdfFile() {
isLoad: true,
message: "This might take some time"
};
setIsLoading(load);
const driveDetails = await getDrive();
if (driveDetails) {
if (driveDetails.length > 0) {
setPdfData(driveDetails);
sortApps(null, null, driveDetails);
}
const data = [
{
name: "OpenSignDrive",
name: "OpenSignDrive",
objectId: ""
}
];
@@ -90,6 +96,7 @@ function PdfFile() {
if (driveDetails) {
if (driveDetails.length > 0) {
setPdfData(driveDetails);
sortApps(null, null, driveDetails);
} else {
setPdfData([]);
}
@@ -111,43 +118,16 @@ function PdfFile() {
setIsFolder(true);
};
//function for handle folder name path
const handleRoute = (data) => {
let loadObj = {
isLoad: true,
message: "This might take some time"
};
if (data.name === "LegaDrive™") {
setIsLoading(loadObj);
if (docId) {
setDocId();
} else {
setTimeout(() => {
const loadObj = {
isLoad: false
};
setIsLoading(loadObj);
}, 1000);
const handleRoute = (index) => {
const updateFolderName = folderName.filter((x, i) => {
if (i <= index) {
return x;
}
} else if (data.name === folderName[folderName.length - 1].name) {
setIsLoading(loadObj);
setTimeout(() => {
const loadObj = {
isLoad: false
};
setIsLoading(loadObj);
}, 1000);
} else {
const findIndex = folderName.findIndex(
(fold) => fold.objectId === data.objectId
);
const newFolder = folderName.slice(0, findIndex + 1);
});
setFolderName(newFolder);
const getLastId = newFolder[newFolder.length - 1];
setDocId(getLastId.objectId);
setIsLoading(loadObj);
}
setFolderName(updateFolderName);
const getLastId = updateFolderName[updateFolderName.length - 1];
setDocId(getLastId.objectId);
};
//function for add new folder name
@@ -156,78 +136,60 @@ function PdfFile() {
const value = e.target.value;
setNewFolderName(value);
};
//function for add folder
//function for create folder
const handleAddFolder = async () => {
if (newFolderName) {
setIsFolderLoader(true);
const getParentObjId = folderName[folderName.length - 1];
const parentId = getParentObjId && getParentObjId.objectId;
let data;
if (parentId) {
data = {
Name: newFolderName,
Type: "Folder",
Folder: {
__type: "Pointer",
className: `${localStorage.getItem("_appName")}_Document`,
objectId: parentId
},
CreatedBy: {
__type: "Pointer",
className: "_User",
objectId: jsonCurrentUser.objectId
}
};
} else {
data = {
Name: newFolderName,
Type: "Folder",
CreatedBy: {
__type: "Pointer",
className: "_User",
objectId: jsonCurrentUser.objectId
}
};
}
const foldercls = `${localStorage.getItem("_appName")}_Document`;
const folderPtr = {
__type: "Pointer",
className: foldercls,
objectId: parentId
};
const CreatedBy = {
__type: "Pointer",
className: "_User",
objectId: jsonCurrentUser.objectId
};
await axios
.post(
`${localStorage.getItem("baseUrl")}classes/${localStorage.getItem(
"_appName"
)}_Document`,
data,
{
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
}
}
)
try {
const exsitQuery = new Parse.Query(foldercls);
exsitQuery.equalTo("Name", newFolderName);
exsitQuery.equalTo("Type", "Folder");
if (parentId) {
exsitQuery.equalTo("Folder", folderPtr);
}
const templExist = await exsitQuery.first();
if (templExist) {
setError("Folder already exist!");
setIsFolderLoader(false);
} else {
const template = new Parse.Object(foldercls);
template.set("Name", newFolderName);
template.set("Type", "Folder");
.then((Listdata) => {
// console.log("Listdata ", Listdata);
const json = Listdata.data;
// console.log("json ", json);
if (json) {
if (parentId) {
template.set("Folder", folderPtr);
}
template.set("CreatedBy", CreatedBy);
const res = await template.save();
if (res) {
const result = JSON.parse(JSON.stringify(res));
setPdfData((prev) => [...prev, result]);
setNewFolderName();
setIsFolderLoader(false);
setIsFolder(false);
if (docId) {
getPdfFolderDocumentList();
} else {
getPdfDocumentList();
}
}
})
.catch((err) => {
setIsAlert({
isShow: true,
alertMessage: "something went wrong"
});
}
} catch (e) {
setIsAlert({
isShow: true,
alertMessage: "something went wrong"
});
}
} else {
setError("Please fill out this field");
}
@@ -249,11 +211,11 @@ function PdfFile() {
}
};
const sortApps = () => {
const selectedSortType = selectedSort;
const sortOrder = sortingOrder;
const sortApps = (type, order, driveDetails) => {
const selectedSortType = type ? type : selectedSort ? selectedSort : "Date";
const sortOrder = order ? order : sortingOrder ? sortingOrder : "Decending";
let sortingData = pdfData;
let sortingData = driveDetails;
if (selectedSortType === "Name") {
sortingApp(sortingData, "Name", sortOrder);
} else if (selectedSortType === "Date") {
@@ -315,9 +277,9 @@ function PdfFile() {
useEffect(() => {
const closeMenuOnOutsideClick = (e) => {
if (isShowSort && !e.target.closest("#menu-container")) {
setIsShowSort(false);
setIsShowSort(!isShowSort);
} else if (isNewFol && !e.target.closest("#folder-menu")) {
setIsNewFol(false);
setIsNewFol(!isNewFol);
}
};
@@ -327,33 +289,56 @@ function PdfFile() {
// Cleanup the event listener when the component unmounts
document.removeEventListener("click", closeMenuOnOutsideClick);
};
}, [isShowSort]);
}, [isShowSort || isNewFol]);
const handleFolderTab = (folderData, isMove) => {
return folderData.map((data, id) => {
return (
<React.Fragment key={id}>
<span
onClick={() => handleRoute(id)}
style={{
color: "#a64b4e",
fontWeight: "400",
cursor: "pointer"
}}
>
{data.name}
<span
style={{
color: "#a64b4e",
fontWeight: "200",
cursor: "pointer",
margin: "0 4px"
}}
>
&gt;
</span>
</span>
</React.Fragment>
);
});
};
const oncloseFolder = () => {
setIsFolder(false);
setNewFolderName("");
setError("");
};
return (
<div className="folderComponent ">
<Title title={"OpenSign™ Drive"} drive={true} />
<div>
<AlertComponent
isShow={isAlert.isShow}
alertMessage={isAlert.alertMessage}
setIsAlert={setIsAlert}
/>
<Modal show={isFolder}>
<ModalHeader style={{ background: themeColor() }}>
<span style={{ color: "white" }}>Add New Folder</span>
{!folderLoader && (
<span
style={{ cursor: "pointer" }}
onClick={() => {
setNewFolderName("");
setIsFolder(false);
}}
>
X
</span>
)}
</ModalHeader>
<Modal.Body>
<ModalUi
isOpen={isFolder}
title={"Add New Folder"}
handleClose={oncloseFolder}
>
<div style={{ height: "100%", padding: 20 }}>
{folderLoader ? (
<div
style={{
@@ -374,7 +359,13 @@ function PdfFile() {
</span>
</div>
) : (
<form style={{ display: "flex", flexDirection: "column" }}>
<form
onSubmit={(e) => {
e.preventDefault();
handleAddFolder();
}}
style={{ display: "flex", flexDirection: "column" }}
>
<label
style={{
margin: "10px 0px 10px 0px",
@@ -393,46 +384,45 @@ function PdfFile() {
onChange={(e) => handleFolderName(e)}
// className="addFolderInput"
/>
<span style={{ color: "red", fontSize: "12px" }}>{error}</span>
<span
style={{ color: "red", fontSize: "12px", marginTop: "6px" }}
>
{error}
</span>
<div
style={{
margin: "20px 10px 10px 10px ",
display: "flex",
alignItems: "flex-end",
justifyContent: "flex-end",
alignContent: "flex-end"
height: "1px",
backgroundColor: "#9f9f9f",
width: "100%",
marginTop: "15px",
marginBottom: "15px"
}}
>
></div>
<div style={{ display: "flex", flexDirection: "row" }}>
<button
type="submit"
style={{
borderRadius: "0px",
border: "1.5px solid #e3e2e1",
fontWeight: "600",
color: "black"
}}
className="finishBtn"
onClick={() => setIsFolder(false)}
>
Close
</button>
<button
onClick={() => handleAddFolder()}
style={{
background: themeColor()
}}
type="button"
type="submit"
className="finishBtn"
>
Add
</button>
<button
style={{
color: "black"
}}
type="button"
className="finishBtn"
onClick={oncloseFolder}
>
Close
</button>
</div>
</form>
)}
</Modal.Body>
</Modal>
</div>
</ModalUi>
{isLoading.isLoad ? (
<div
@@ -479,31 +469,7 @@ function PdfFile() {
}}
className="folderPath"
>
{folderName.map((data, id) => {
return (
<span
key={id}
onClick={() => handleRoute(data)}
style={{
color: "#a64b4e",
fontWeight: "400",
cursor: "pointer"
}}
>
{data.name}
<span
style={{
color: "#a64b4e",
fontWeight: "200",
cursor: "pointer",
margin: "0 4px"
}}
>
&gt;
</span>
</span>
);
})}
{handleFolderTab(folderName)}
</div>
<div className="dropMenuBD">
<div
@@ -603,7 +569,7 @@ function PdfFile() {
<span
onClick={() => {
setSelectedSort("Name");
sortApps();
sortApps("Name", null, pdfData);
}}
className="dropdown-item itemColor"
>
@@ -625,7 +591,7 @@ function PdfFile() {
<span
onClick={() => {
setSelectedSort("Date");
sortApps();
sortApps("Date", null, pdfData);
}}
className="dropdown-item itemColor"
>
@@ -648,7 +614,7 @@ function PdfFile() {
<span
onClick={() => {
setSortingOrder("Accending");
sortApps();
sortApps(null, "Accending", pdfData);
}}
className="dropdown-item itemColor"
>
@@ -670,7 +636,7 @@ function PdfFile() {
<span
onClick={() => {
setSortingOrder("Decending");
sortApps();
sortApps(null, "Decending", pdfData);
}}
className="dropdown-item itemColor"
>
@@ -736,7 +736,7 @@ function PdfRequestFiles() {
<CustomModal
containerWH={containerWH}
show={isDecline.isDeclined}
headMsg="Document Declined Alert!"
headMsg="Document Declined"
bodyMssg={
isDecline.currnt === "Sure" ? (
<p className="pTagBody">
@@ -660,7 +660,10 @@ const TemplatePlaceholder = () => {
const data = {
Placeholders: signerPos,
SignedUrl: pdfDetails[0].URL,
Signers: signers
Signers: signers,
Name: pdfDetails[0]?.Name || "",
Note: pdfDetails[0]?.Note || "",
Description: pdfDetails[0]?.Description || ""
};
await axios
@@ -25,39 +25,41 @@ function CustomModal({
<div className="modalHeadDiv bg-danger">{headMsg && headMsg}</div>
<div className="modalBodyDIv">
<p className="pTagBody">{bodyMssg && bodyMssg}</p>
<div
style={{
height: "1px",
backgroundColor: "#9f9f9f",
width: "100%",
marginTop: "15px",
marginBottom: "15px"
}}
></div>
{footerMessage && (
<div className="modalFooterDiv">
<button
<>
<div
style={{
background: "#de4337"
height: "1px",
backgroundColor: "#9f9f9f",
width: "100%",
marginTop: "15px",
marginBottom: "15px"
}}
type="button"
className="finishBtn"
onClick={() => declineDoc()}
>
Yes
</button>
<button
style={{
color: "black"
}}
type="button"
className="finishBtn"
onClick={() => setIsDecline({ isDeclined: false })}
>
Close
</button>
</div>
></div>
<div className="modalFooterDiv">
<button
style={{
background: "#de4337"
}}
type="button"
className="finishBtn"
onClick={() => declineDoc()}
>
Yes
</button>
<button
style={{
color: "black"
}}
type="button"
className="finishBtn"
onClick={() => setIsDecline({ isDeclined: false })}
>
Close
</button>
</div>
</>
)}
</div>
</div>
@@ -1,10 +1,10 @@
import React from "react";
import { Helmet } from "react-helmet";
function Title({ title }) {
function Title({ title, drive }) {
return (
<Helmet>
<title>{`${title} - OpenSign™`}</title>
<title>{drive ? title : `${title} - OpenSign™`}</title>
<meta name="description" content={`${title} - OpenSign™`} />
<link
rel="icon"
@@ -639,6 +639,7 @@ function PlaceHolderSign() {
setIsSendAlert(alert);
}
};
const sendEmailToSigners = async () => {
const loadObj = {
isLoad: true,
@@ -720,15 +721,33 @@ function PlaceHolderSign() {
objectId: x.objectId
};
});
const addExtraDays = pdfDetails[0]?.TimeToCompleteDays
? pdfDetails[0].TimeToCompleteDays
: 15;
const currentUser = signersdata.find((x) => x.Email === currentId);
setCurrentId(currentUser?.objectId);
let updateExpiryDate, data;
updateExpiryDate = new Date();
updateExpiryDate.setDate(updateExpiryDate.getDate() + addExtraDays);
try {
const data = {
Placeholders: signerPos,
SignedUrl: pdfDetails[0].URL,
Signers: signers
};
if (updateExpiryDate) {
data = {
Placeholders: signerPos,
SignedUrl: pdfDetails[0].URL,
Signers: signers,
ExpiryDate: {
iso: updateExpiryDate,
__type: "Date"
}
};
} else {
data = {
Placeholders: signerPos,
SignedUrl: pdfDetails[0].URL,
Signers: signers
};
}
await axios
.put(
+3 -1
View File
@@ -10,7 +10,9 @@ import PdfRequestFiles from "./Component/PdfRequestFiles";
import LegaDrive from "./Component/LegaDrive/LegaDrive";
import PageNotFound from "./Component/PageNotFound";
import TemplatePlaceHolder from "./Component/TemplatePlaceholder";
import Parse from "parse";
Parse.serverURL = localStorage.getItem("baseUrl");
Parse.initialize(localStorage.getItem("parseAppId"));
// `AppRoutes` is used to define route path of app and
// it expose to host app, check moduleFederation.config.js for more
function AppRoutes() {
@@ -0,0 +1,6 @@
.hrStyle{
border-top-width: 1px !important;
color: #c3bcbc !important;
height: 0px !important;
margin-bottom: 10px !important;
}
@@ -1,6 +1,7 @@
import React, { useEffect, useState } from "react";
import Parse from "parse";
import Alert from "./Alert";
import { themeColor } from "../utils/ThemeColor/backColor";
const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
const folderPtr = {
@@ -20,7 +21,7 @@ const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
const fetchFolder = async () => {
try {
const FolderQuery = new Parse.Query(folderCls);
const FolderQuery = new Parse.Query(folderCls);
if (parentFolderId) {
FolderQuery.equalTo("Folder", folderPtr);
FolderQuery.equalTo("Type", "Folder");
@@ -74,6 +75,7 @@ const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
template.set("CreatedBy", Parse.User.createWithoutData(currentUser.id));
const res = await template.save();
if (res) {
const result = JSON.parse(JSON.stringify(res));
if (onSuccess) {
setAlert({
type: "success",
@@ -83,7 +85,7 @@ const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
setTimeout(() => {
setIsAlert(false);
}, 1000);
onSuccess(res);
onSuccess(result);
}
}
}
@@ -98,28 +100,43 @@ const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
const handleOptions = (e) => {
setSelectedParent(e.target.value);
};
return (
<div>
{isAlert && <Alert type={alert.type}>{alert.message}</Alert>}
<div id="createFolder">
<h1 className="text-base font-semibold">Create Folder</h1>
<div className="text-xs mt-2">
<h1 style={{ fontWeight: "500", fontSize: "1rem" }}>Create Folder</h1>
<div style={{ fontSize: "12px", marginTop: "11px" }}>
<label className="block">
Name<span style={{ color: "red", fontSize: 13 }}> *</span>
Name<span style={{ color: "red", fontSize: "13px" }}> *</span>
</label>
<input
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
style={{
padding: "8px 11px",
width: "100%",
border: "1px solid rgb(195, 188, 188)",
borderRadius: "5px",
outline: "none",
fontSize: "12px"
}}
value={name}
onChange={(e) => setName(e.target.value)}
required
/>
</div>
<div className="text-xs mt-2">
<div style={{ fontSize: "12px", marginTop: "7px" }}>
<label className="block">Parent Folder</label>
<select
value={selectedParent}
onChange={handleOptions}
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
style={{
padding: "8px 11px",
width: "100%",
border: "1px solid rgb(195, 188, 188)",
borderRadius: "5px",
outline: "none",
fontSize: "12px"
}}
>
<option>select</option>
{folderList.length > 0 &&
@@ -133,7 +150,18 @@ const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
<div>
<button
onClick={handleCreateFolder}
className="flex items-center rounded p-2 bg-[#33bbff] text-white mt-3"
style={{
display: "flex",
alignItems: "center",
borderRadius: "5px",
backgroundColor: themeColor(),
color: "white",
marginTop: "22px",
outline: "none",
border: "none",
padding: "10px 8px",
fontSize: "14px"
}}
>
<i className="fa-solid fa-plus mr-1"></i>
<span>Create</span>
@@ -1,48 +1,61 @@
import React, { useEffect, useState } from "react";
import Parse from "parse";
import CreateFolder from "./CreateFolder";
import ModalUi from './ModalUi'
import ModalUi from "./ModalUi";
import axios from "axios";
import { themeColor } from "../utils/ThemeColor/backColor";
import "../css/selectFolder.css";
const SelectFolder = ({ required, onSuccess, folderCls }) => {
const [isOpen, SetIsOpen] = useState(false);
const SelectFolder = ({
required,
onSuccess,
folderCls,
isOpenModal,
setIsOpenMoveModal,
setPdfData
}) => {
const [clickFolder, setClickFolder] = useState("");
const [selectFolder, setSelectedFolder] = useState({});
// const [selectFolder, setSelectedFolder] = useState({});
const [folderList, setFolderList] = useState([]);
const [tabList, setTabList] = useState([]);
const [isLoader, setIsLoader] = useState(false);
const [folderPath, setFolderPath] = useState("");
// const [folderPath, setFolderPath] = useState("");
const [isAdd, setIsAdd] = useState(false);
useEffect(() => {
if (isOpen) {
if (isOpenModal) {
setIsAdd(false);
setClickFolder({});
setFolderList([]);
setTabList([]);
fetchFolder();
}
}, [isOpen]);
}, []);
//fetch folder data
const fetchFolder = async (folderPtr) => {
setIsLoader(true);
try {
const FolderQuery = new Parse.Query(folderCls);
if (folderPtr) {
FolderQuery.equalTo("Folder", folderPtr);
FolderQuery.equalTo("Type", "Folder");
} else {
FolderQuery.doesNotExist("Folder");
FolderQuery.equalTo("Type", "Folder");
}
let url;
const classUrl = `${localStorage.getItem("baseUrl")}classes/${folderCls}`;
const res = await FolderQuery.find();
if (res) {
const result = JSON.parse(JSON.stringify(res));
if (result) {
setFolderList(result);
setIsLoader(false);
if (folderPtr) {
url = `${classUrl}?where={"Folder": {"__type":"Pointer","className":"${folderCls}","objectId":"${folderPtr.objectId}"},"Type":"Folder"}`;
} else {
url = `${classUrl}?where={"Folder":{"$exists":false},"Type":"Folder"}`;
}
try {
const res = await axios.get(url, {
headers: {
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
}
});
if (res.data.results) {
setFolderList(res.data.results);
setIsLoader(false);
setIsAdd(false);
}
} catch (error) {
setIsLoader(false);
} catch (err) {
console.log("err", err);
setIsLoader(false);
}
};
@@ -77,15 +90,15 @@ const SelectFolder = ({ required, onSuccess, folderCls }) => {
tabList.forEach((t) => {
url = url + " / " + t.Name;
});
setFolderPath(url);
setSelectedFolder(clickFolder);
// setFolderPath(url);
// setSelectedFolder(clickFolder);
if (onSuccess) {
onSuccess(clickFolder);
}
SetIsOpen(false);
setIsOpenMoveModal(false);
};
const handleCancel = () => {
SetIsOpen(false);
setIsOpenMoveModal(false);
setClickFolder({});
setFolderList([]);
setTabList([]);
@@ -113,7 +126,7 @@ const SelectFolder = ({ required, onSuccess, folderCls }) => {
setTabList(list);
} else {
setClickFolder({});
setSelectedFolder({});
// setSelectedFolder({});
setFolderList([]);
setTabList([]);
}
@@ -123,7 +136,8 @@ const SelectFolder = ({ required, onSuccess, folderCls }) => {
const handleCreate = () => {
setIsAdd(!isAdd);
};
const handleAddFolder = () => {
const handleAddFolder = (res) => {
setPdfData((prev) => [...prev, res]);
setFolderList([]);
if (clickFolder && clickFolder.ObjectId) {
fetchFolder({
@@ -135,212 +149,134 @@ const SelectFolder = ({ required, onSuccess, folderCls }) => {
fetchFolder();
}
};
return (
<div className="text-xs mt-2">
<div>
<label className="block">
Select Folder
{required && <span style={{ color: "red", fontSize: 13 }}> *</span>}
</label>
</div>
<div className="rounded px-[20px] py-[20px] bg-white border border-gray-200 shadow flex max-w-sm gap-8 items-center">
<div>
<i
className="far fa-folder-open text-[40px] text-[#33bbff]"
style={{ fontSize: "40px" }}
aria-hidden="true"
></i>
</div>
<div className="font-semibold ">
<div className="flex items-center gap-2">
<p>
{selectFolder && selectFolder.Name ? selectFolder.Name : "Root"}
</p>
<div className="text-black text-sm" onClick={() => SetIsOpen(true)}>
<i
className="fa fa-pencil"
title="Select Folder"
aria-hidden="true"
></i>
</div>
</div>
<p className="text-[10px] text-gray-400">
{selectFolder && selectFolder.Name ? `(${folderPath})` : ""}
</p>
</div>
</div>
<ModalUi id="asd" title={"Select Folder"} isOpen={isOpen} handleClose={handleCancel}> <div className="w-full min-w-[300px] md:min-w-[500px] px-3">
<div className="py-2 text-[#ac4848] text-[14px] font-[500]">
<span
className="cursor-pointer"
title="Root"
onClick={(e) => removeTabListItem(e)}
>
Root /{" "}
</span>
{tabList &&
tabList.map((tab, i) => (
<React.Fragment key={`${tab.objectId}-${i}`}>
<span
className="cursor-pointer"
title={tab.Name}
onClick={(e) => removeTabListItem(e, i)}
>
{tab.Name}
</span>
{" / "}
</React.Fragment>
))}
<hr />
</div>
<div className="mt-2 mb-3">
{!isAdd &&
folderList.length > 0 &&
folderList.map((folder) => (
<div
key={folder.Name}
className="border-[1px] border-[#8a8a8a] px-2 py-2 mb-2 cursor-pointer"
onClick={() => handleSelect(folder)}
<div>
<ModalUi
id="asd"
title={"Select Folder"}
isOpen={isOpenModal}
handleClose={handleCancel}
>
{" "}
<div style={{ width: "100%", padding: "1rem" }}>
<div
style={{
paddingTop: "2px",
color: "#ac4848",
fontSize: "14px",
fontWeight: "500"
}}
>
<span
style={{ cursor: "pointer" }}
title="Root"
onClick={(e) => {
setIsAdd(false);
removeTabListItem(e);
}}
>
Root /{" "}
</span>
{tabList &&
tabList.map((tab, i) => (
<React.Fragment key={`${tab.objectId}-${i}`}>
<span
style={{ cursor: "pointer" }}
title={tab.Name}
onClick={(e) => {
setIsAdd(false);
removeTabListItem(e, i);
}}
>
<div className="flex items-center gap-2">
<i
className="fa fa-folder text-[#33bbff] text-[1.4rem]"
aria-hidden="true"
></i>
<span className="font-semibold">{folder.Name}</span>
</div>
</div>
))}
{isAdd && (
<CreateFolder
parentFolderId={clickFolder && clickFolder.ObjectId}
folderCls={folderCls}
onSuccess={handleAddFolder}
/>
)}
{isLoader && (
<div className="flex justify-center">
<i className="fa-solid fa-spinner fa-spin-pulse text-[30px]"></i>
</div>
)}
</div>
{tab.Name}
</span>
{" / "}
</React.Fragment>
))}
<hr className="hrStyle" />
</div>
<hr />
<div className="flex justify-between items-center py-[.75rem] px-[1.25rem]">
<div
className="text-[30px] cursor-pointer text-[#33bbff]"
title="Save Here"
onClick={handleCreate}
>
{isAdd ? (
<i className="fa-solid fa-arrow-left" aria-hidden="true"></i>
) : (
<i className="fa-solid fa-square-plus" aria-hidden="true"></i>
)}
</div>
<div
className="text-[30px] cursor-pointer"
title="Save Here"
onClick={handleSubmit}
>
<i className="fas fa-save" aria-hidden="true"></i>
</div>
</div></ModalUi>
{/* {isOpen && (
<div style={{ margin: "2px 0 3px 0" }}>
{!isAdd &&
folderList.length > 0 &&
folderList.map((folder) => (
<div
key={folder.Name}
style={{
border: "1.7px solid #c3bcbc",
padding: "6px",
marginBottom: "5px",
cursor: "pointer"
}}
onClick={() => handleSelect(folder)}
>
<div
style={{ display: "flex", alignItems: "center", gap: "2" }}
>
<i
style={{ color: "#33bbff", fontSize: "1.4rem" }}
className="fa fa-folder "
aria-hidden="true"
></i>
<span
style={{
fontWeight: "500",
marginLeft: "10px",
fontSize: "14px"
}}
>
{folder.Name}
</span>
</div>
</div>
))}
{isAdd && (
<CreateFolder
parentFolderId={clickFolder && clickFolder.ObjectId}
folderCls={folderCls}
onSuccess={handleAddFolder}
setIsAdd={setIsAdd}
/>
)}
{isLoader && (
<div style={{ display: "flex", justifyContent: "center" }}>
<i
style={{ fontSize: "30px" }}
className="fa-solid fa-spinner fa-spin-pulse "
></i>
</div>
)}
</div>
</div>
<hr className="hrStyle" />
<div
className={`fixed z-40 top-20 left-1/2 transform -translate-x-1/2 border-[1px] text-sm bg-white rounded `}
style={{
display: "flex",
justifyContent: "space-between",
alignItems: "center",
padding: "0px 16px 12px 16px"
}}
>
<div className="flex justify-between items-center py-[.75rem] px-[1.25rem] bg-[#f5f5f5]">
<div className="font-semibold text-lg text-black">
Select Folder
</div>
<div
onClick={handleCancel}
className="px-2 py-1 border-[1px] border-[#8a8a8a] bg-white rounded cursor-pointer"
>
<i className="fa-solid fa-xmark"></i>
</div>
<div
style={{ fontSize: "30px", cursor: "pointer", color: themeColor() }}
title="Save Here"
onClick={handleCreate}
>
{isAdd ? (
<i className="fa-solid fa-arrow-left" aria-hidden="true"></i>
) : (
<i className="fa-solid fa-square-plus" aria-hidden="true"></i>
)}
</div>
<hr />
<div className="w-full min-w-[300px] md:min-w-[500px] px-3">
<div className="py-2 text-[#ac4848] text-[14px] font-[500]">
<span
className="cursor-pointer"
title="Root"
onClick={(e) => removeTabListItem(e)}
>
Root /{" "}
</span>
{tabList &&
tabList.map((tab, i) => (
<React.Fragment key={`${tab.objectId}-${i}`}>
<span
className="cursor-pointer"
title={tab.Name}
onClick={(e) => removeTabListItem(e, i)}
>
{tab.Name}
</span>
{" / "}
</React.Fragment>
))}
<hr />
</div>
<div className="mt-2 mb-3">
{!isAdd &&
folderList.length > 0 &&
folderList.map((folder) => (
<div
key={folder.Name}
className="border-[1px] border-[#8a8a8a] px-2 py-2 mb-2 cursor-pointer"
onClick={() => handleSelect(folder)}
>
<div className="flex items-center gap-2">
<i
className="fa fa-folder text-[#33bbff] text-[1.4rem]"
aria-hidden="true"
></i>
<span className="font-semibold">{folder.Name}</span>
</div>
</div>
))}
{isAdd && (
<CreateFolder
parentFolderId={clickFolder && clickFolder.ObjectId}
folderCls={folderCls}
onSuccess={handleAddFolder}
/>
)}
{isLoader && (
<div className="flex justify-center">
<i className="fa-solid fa-spinner fa-spin-pulse text-[30px]"></i>
</div>
)}
</div>
</div>
<hr />
<div className="flex justify-between items-center py-[.75rem] px-[1.25rem]">
<div
className="text-[30px] cursor-pointer text-[#33bbff]"
title="Save Here"
onClick={handleCreate}
>
{isAdd ? (
<i className="fa-solid fa-arrow-left" aria-hidden="true"></i>
) : (
<i className="fa-solid fa-square-plus" aria-hidden="true"></i>
)}
</div>
<div
className="text-[30px] cursor-pointer"
title="Save Here"
onClick={handleSubmit}
>
<i className="fas fa-save" aria-hidden="true"></i>
</div>
<div
style={{ fontSize: "30px", cursor: "pointer" }}
title="Save Here"
onClick={handleSubmit}
>
<i className="fas fa-save" aria-hidden="true"></i>
</div>
</div>
)} */}
</ModalUi>
</div>
);
};