mirror of
https://github.com/OpenSignLabs/OpenSign.git
synced 2026-08-21 15:12:34 +02:00
add new template form
This commit is contained in:
@@ -46,6 +46,7 @@ const AppendFormInForm = (props) => {
|
||||
// Define a function to handle form submission
|
||||
const handleSubmit = async (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
setIsLoader(true);
|
||||
Parse.serverURL = parseBaseUrl;
|
||||
Parse.initialize(parseAppId);
|
||||
|
||||
@@ -5,7 +5,7 @@ import Parse from "parse";
|
||||
import axios from "axios";
|
||||
import "../styles/spinner.css";
|
||||
import TreeFormComponent from "./TreeFormComponent";
|
||||
import TreeEditForm from "./TreeEditForm";
|
||||
// import TreeEditForm from "./TreeEditForm";
|
||||
import "../styles/modal.css";
|
||||
import Modal from "react-modal";
|
||||
|
||||
@@ -22,7 +22,7 @@ const TreeWidget = (props) => {
|
||||
const [schemaState, setSchemaState] = useState({});
|
||||
const [TabURL, setTabURL] = useState("");
|
||||
const [editable, setEditable] = useState(false);
|
||||
const [editId, setEditId] = useState("");
|
||||
// const [editId, setEditId] = useState("");
|
||||
const [defaultState, setDefaultState] = useState(false);
|
||||
const [isShowModal, setIsShowModal] = useState(false);
|
||||
const selectFolderHandle = async () => {
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import Parse from "parse";
|
||||
import { templateCls } from "../../constant/const";
|
||||
import Alert from "../../primitives/Alert";
|
||||
|
||||
const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
|
||||
const folderPtr = {
|
||||
__type: "Pointer",
|
||||
className: folderCls,
|
||||
objectId: parentFolderId
|
||||
};
|
||||
const [name, setName] = useState("");
|
||||
const [folderList, setFolderList] = useState([]);
|
||||
const [isAlert, setIsAlert] = useState(false);
|
||||
const [selectedParent, setSelectedParent] = useState();
|
||||
const [alert, setAlert] = useState({ type: "info", message: "" });
|
||||
useEffect(() => {
|
||||
fetchFolder();
|
||||
// eslint-disable-next-line
|
||||
}, []);
|
||||
|
||||
const fetchFolder = async () => {
|
||||
try {
|
||||
const fetchFolder = new Parse.Query(folderCls);
|
||||
if (parentFolderId) {
|
||||
fetchFolder.equalTo("Folder", folderPtr);
|
||||
fetchFolder.equalTo("Type", "Folder");
|
||||
} else {
|
||||
fetchFolder.doesNotExist("Folder");
|
||||
fetchFolder.equalTo("Type", "Folder");
|
||||
}
|
||||
|
||||
const res = await fetchFolder.find();
|
||||
if (res) {
|
||||
const result = JSON.parse(JSON.stringify(res));
|
||||
if (result) {
|
||||
setFolderList(result);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.log("Err ", error);
|
||||
}
|
||||
};
|
||||
const handleCreateFolder = async (event) => {
|
||||
event.preventDefault();
|
||||
if (name) {
|
||||
const currentUser = Parse.User.current();
|
||||
const exsitQuery = new Parse.Query(templateCls);
|
||||
exsitQuery.equalTo("Name", name);
|
||||
exsitQuery.equalTo("Type", "Folder");
|
||||
if (parentFolderId) {
|
||||
exsitQuery.equalTo("Folder", folderPtr);
|
||||
}
|
||||
const templExist = await exsitQuery.first();
|
||||
if (templExist) {
|
||||
setAlert({ type: "dange", message: "Folder already exist!" });
|
||||
setIsAlert(true);
|
||||
setTimeout(() => {
|
||||
setIsAlert(false);
|
||||
}, 1000);
|
||||
} else {
|
||||
const template = new Parse.Object(templateCls);
|
||||
template.set("Name", name);
|
||||
template.set("Type", "Folder");
|
||||
|
||||
if (selectedParent) {
|
||||
template.set("Folder", {
|
||||
__type: "Pointer",
|
||||
className: folderCls,
|
||||
objectId: selectedParent
|
||||
});
|
||||
} else if (parentFolderId) {
|
||||
template.set("Folder", folderPtr);
|
||||
}
|
||||
template.set("CreatedBy", Parse.User.createWithoutData(currentUser.id));
|
||||
const res = await template.save();
|
||||
if (res) {
|
||||
if (onSuccess) {
|
||||
setAlert({
|
||||
type: "success",
|
||||
message: "Folder created successfully!"
|
||||
});
|
||||
setIsAlert(true);
|
||||
setTimeout(() => {
|
||||
setIsAlert(false);
|
||||
}, 1000);
|
||||
onSuccess(res);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
setAlert({ type: "info", message: "Please fill folder name" });
|
||||
setIsAlert(true);
|
||||
setTimeout(() => {
|
||||
setIsAlert(false);
|
||||
}, 1000);
|
||||
}
|
||||
};
|
||||
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">
|
||||
<label className="block">
|
||||
Name<span className="text-red-500 text-[13px]">*</span>
|
||||
</label>
|
||||
<input
|
||||
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
|
||||
value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div className="text-xs mt-2">
|
||||
<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"
|
||||
>
|
||||
<option>select</option>
|
||||
{folderList.length > 0 &&
|
||||
folderList.map((x) => (
|
||||
<option key={x.objectId} value={x.objectId}>
|
||||
{x.Name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<button
|
||||
onClick={handleCreateFolder}
|
||||
className="flex items-center rounded p-2 bg-[#33bbff] text-white mt-3"
|
||||
>
|
||||
<i className="fa-solid fa-plus mr-1"></i>
|
||||
<span>Create</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default CreateFolder;
|
||||
@@ -271,10 +271,12 @@ const FileUpload = (props) => {
|
||||
<i className="fa-solid fa-xmark"></i>
|
||||
</div>
|
||||
</div>
|
||||
<DropboxChooser
|
||||
onSuccess={dropboxSuccess}
|
||||
onCancel={dropboxCancel}
|
||||
/>
|
||||
{process.env.DROPBOX_APP_KEY && (
|
||||
<DropboxChooser
|
||||
onSuccess={dropboxSuccess}
|
||||
onCancel={dropboxCancel}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex gap-2 justify-center items-center">
|
||||
@@ -294,10 +296,12 @@ const FileUpload = (props) => {
|
||||
accept="application/pdf,application/vnd.ms-excel"
|
||||
onChange={onChange}
|
||||
/>
|
||||
<DropboxChooser
|
||||
onSuccess={dropboxSuccess}
|
||||
onCancel={dropboxCancel}
|
||||
/>
|
||||
{process.env.DROPBOX_APP_KEY && (
|
||||
<DropboxChooser
|
||||
onSuccess={dropboxSuccess}
|
||||
onCancel={dropboxCancel}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
|
||||
@@ -0,0 +1,271 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import Parse from "parse";
|
||||
import CreateFolder from "./CreateFolder";
|
||||
import { templateCls } from "../../constant/const";
|
||||
|
||||
const SelectFolder = ({ required, onSuccess }) => {
|
||||
const [isOpen, SetIsOpen] = useState(false);
|
||||
const [clickFolder, setClickFolder] = useState("");
|
||||
const [selectFolder, setSelectedFolder] = useState({});
|
||||
const [folderList, setFolderList] = useState([]);
|
||||
const [tabList, setTabList] = useState([]);
|
||||
const [isLoader, setIsLoader] = useState(false);
|
||||
const [folderPath, setFolderPath] = useState("");
|
||||
const [isAdd, setIsAdd] = useState(false);
|
||||
useEffect(() => {
|
||||
if (isOpen) {
|
||||
setIsAdd(false);
|
||||
setClickFolder({});
|
||||
setFolderList([]);
|
||||
setTabList([]);
|
||||
fetchFolder();
|
||||
}
|
||||
}, [isOpen]);
|
||||
const fetchFolder = async (folderPtr) => {
|
||||
setIsLoader(true);
|
||||
try {
|
||||
const fetchFolder = new Parse.Query(templateCls);
|
||||
if (folderPtr) {
|
||||
fetchFolder.equalTo("Folder", folderPtr);
|
||||
fetchFolder.equalTo("Type", "Folder");
|
||||
} else {
|
||||
fetchFolder.doesNotExist("Folder");
|
||||
fetchFolder.equalTo("Type", "Folder");
|
||||
}
|
||||
|
||||
const res = await fetchFolder.find();
|
||||
if (res) {
|
||||
const result = JSON.parse(JSON.stringify(res));
|
||||
if (result) {
|
||||
setFolderList(result);
|
||||
setIsLoader(false);
|
||||
}
|
||||
setIsLoader(false);
|
||||
}
|
||||
} catch (error) {
|
||||
setIsLoader(false);
|
||||
}
|
||||
};
|
||||
const handleSelect = (item) => {
|
||||
setFolderList([]);
|
||||
setClickFolder({ ObjectId: item.objectId, Name: item.Name });
|
||||
if (tabList.length > 0) {
|
||||
const tab = tabList.some((x) => x.objectId === item.objectId);
|
||||
if (!tab) {
|
||||
setTabList((tabs) => [...tabs, item]);
|
||||
const folderPtr = {
|
||||
__type: "Pointer",
|
||||
className: templateCls,
|
||||
objectId: item.objectId
|
||||
};
|
||||
fetchFolder(folderPtr);
|
||||
}
|
||||
} else {
|
||||
setTabList((tabs) => [...tabs, item]);
|
||||
const folderPtr = {
|
||||
__type: "Pointer",
|
||||
className: templateCls,
|
||||
objectId: item.objectId
|
||||
};
|
||||
|
||||
fetchFolder(folderPtr);
|
||||
}
|
||||
};
|
||||
|
||||
const handleSubmit = () => {
|
||||
let url = "Root";
|
||||
tabList.forEach((t) => {
|
||||
url = url + " / " + t.Name;
|
||||
});
|
||||
setFolderPath(url);
|
||||
setSelectedFolder(clickFolder);
|
||||
if (onSuccess) {
|
||||
onSuccess(clickFolder);
|
||||
}
|
||||
SetIsOpen(false);
|
||||
};
|
||||
const handleCancel = () => {
|
||||
SetIsOpen(false);
|
||||
setClickFolder({});
|
||||
setFolderList([]);
|
||||
setTabList([]);
|
||||
};
|
||||
|
||||
const removeTabListItem = async (e, i) => {
|
||||
e.preventDefault();
|
||||
// setEditable(false);
|
||||
if (!isAdd) {
|
||||
setIsLoader(true);
|
||||
let folderPtr;
|
||||
if (i) {
|
||||
setFolderList([]);
|
||||
let list = tabList.filter((itm, j) => {
|
||||
if (j <= i) {
|
||||
return itm;
|
||||
}
|
||||
});
|
||||
let _len = list.length - 1;
|
||||
folderPtr = {
|
||||
__type: "Pointer",
|
||||
className: templateCls,
|
||||
objectId: list[_len].objectId
|
||||
};
|
||||
setTabList(list);
|
||||
} else {
|
||||
setClickFolder({});
|
||||
setSelectedFolder({});
|
||||
setFolderList([]);
|
||||
setTabList([]);
|
||||
}
|
||||
fetchFolder(folderPtr);
|
||||
}
|
||||
};
|
||||
const handleCreate = () => {
|
||||
setIsAdd(!isAdd);
|
||||
};
|
||||
const handleAddFolder = () => {
|
||||
setFolderList([]);
|
||||
if (clickFolder && clickFolder.ObjectId) {
|
||||
fetchFolder({
|
||||
__type: "Pointer",
|
||||
className: templateCls,
|
||||
objectId: clickFolder.ObjectId
|
||||
});
|
||||
} else {
|
||||
fetchFolder();
|
||||
}
|
||||
};
|
||||
return (
|
||||
<div className="text-xs mt-2 ">
|
||||
<div>
|
||||
<label className="block">
|
||||
Select Folder
|
||||
{required && <span className="text-red-500 text-[13px]">*</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>
|
||||
{isOpen && (
|
||||
<div
|
||||
className={`fixed z-40 top-20 left-1/2 transform -translate-x-1/2 border-[1px] text-sm bg-white rounded `}
|
||||
>
|
||||
<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>
|
||||
<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={templateCls}
|
||||
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>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SelectFolder;
|
||||
@@ -0,0 +1,190 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import Select from "react-select";
|
||||
import AppendFormInForm from "../AppendFormInForm";
|
||||
import Modal from "react-modal";
|
||||
import Parse from "parse";
|
||||
function arrayMove(array, from, to) {
|
||||
array = array.slice();
|
||||
array.splice(to < 0 ? array.length + to : to, 0, array.splice(from, 1)[0]);
|
||||
return array;
|
||||
}
|
||||
|
||||
/**
|
||||
* react-sortable-hoc is depcreated not usable from react 18.x.x
|
||||
* need to replace it with @dnd-kit
|
||||
* code changes required
|
||||
*/
|
||||
|
||||
const SignersInput = (props) => {
|
||||
Modal.setAppElement("body");
|
||||
const [state, setState] = useState(undefined);
|
||||
// const [editFormData, setEditFormData] = useState([]);
|
||||
const [selected, setSelected] = React.useState([]);
|
||||
const [isModal, setIsModel] = useState(false);
|
||||
const onChange = (selectedOptions) => setSelected(selectedOptions);
|
||||
const [modalIsOpen, setModalIsOpen] = useState(false);
|
||||
|
||||
const onSortEnd = ({ oldIndex, newIndex }) => {
|
||||
const newValue = arrayMove(selected, oldIndex, newIndex);
|
||||
setSelected(newValue);
|
||||
};
|
||||
|
||||
const GetSelectListData = async () => {
|
||||
try {
|
||||
const currentUser = Parse.User.current();
|
||||
const contactbook = new Parse.Query("contracts_Contactbook");
|
||||
contactbook.equalTo(
|
||||
"CreatedBy",
|
||||
Parse.User.createWithoutData(currentUser.id)
|
||||
);
|
||||
contactbook.notEqualTo("IsDeleted", true);
|
||||
const contactRes = await contactbook.find();
|
||||
if (contactRes) {
|
||||
const res = JSON.parse(JSON.stringify(contactRes));
|
||||
let list = [];
|
||||
|
||||
// let _selected = [];
|
||||
res.forEach((x) => {
|
||||
let obj = {
|
||||
label: x.Name,
|
||||
value: x.objectId,
|
||||
isChecked: true
|
||||
};
|
||||
|
||||
list.push(obj);
|
||||
});
|
||||
setState(list);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log("err", error);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
GetSelectListData();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (selected && selected.length) {
|
||||
let newData = [];
|
||||
selected.forEach((x) => {
|
||||
newData.push(x.value);
|
||||
});
|
||||
if (props.onChange) {
|
||||
props.onChange(newData);
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line
|
||||
}, [selected]);
|
||||
|
||||
const handleModalCloseClick = () => {
|
||||
setIsModel(false);
|
||||
setModalIsOpen(false);
|
||||
};
|
||||
|
||||
const openModal = () => {
|
||||
setModalIsOpen(true);
|
||||
};
|
||||
|
||||
// `handleNewDetails` is used to set just save from quick form to selected option in dropdown
|
||||
const handleNewDetails = (data) => {
|
||||
setState([...state, data]);
|
||||
if (selected.length > 0) {
|
||||
setSelected([...selected, data]);
|
||||
} else {
|
||||
setSelected([data]);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="text-xs mt-2 ">
|
||||
<label className="block">
|
||||
Signers
|
||||
{props.required && <span className="text-red-500 text-[13px]">*</span>}
|
||||
</label>
|
||||
<div style={{ display: "flex", gap: 5 }}>
|
||||
<div style={{ flexWrap: "wrap", width: "100%" }}>
|
||||
<Select
|
||||
onSortEnd={onSortEnd}
|
||||
distance={4}
|
||||
isMulti
|
||||
options={state || []}
|
||||
value={selected}
|
||||
onChange={onChange}
|
||||
closeMenuOnSelect={false}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
onClick={() => {
|
||||
setIsModel(true);
|
||||
openModal();
|
||||
}}
|
||||
style={{
|
||||
cursor: "pointer",
|
||||
borderRadius: 4,
|
||||
border: "1px solid #ccc",
|
||||
minHeight: 38,
|
||||
minWidth: 48,
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center"
|
||||
}}
|
||||
>
|
||||
<i className="fas fa-plus"></i>
|
||||
</div>
|
||||
<Modal
|
||||
isOpen={modalIsOpen}
|
||||
onRequestClose={handleModalCloseClick}
|
||||
shouldCloseOnOverlayClick={false}
|
||||
id="modal1"
|
||||
contentLabel="Modal"
|
||||
style={{
|
||||
content: {
|
||||
top: "50%",
|
||||
left: "50%",
|
||||
right: "auto",
|
||||
bottom: "auto",
|
||||
transform: "translate(-50%, -50%)",
|
||||
padding: 0
|
||||
},
|
||||
overlay: {
|
||||
width: "100%",
|
||||
backgroundColor: "rgba(0, 0, 0, 0.75)",
|
||||
zIndex: 50
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div className="min-w-full md:min-w-[500px]">
|
||||
<div
|
||||
type="button"
|
||||
className="flex justify-between items-center p-3 border-b-[1px] border-gray-300"
|
||||
>
|
||||
<div className=" text-black text-xl font-semibold pl-3">
|
||||
Add Signer
|
||||
</div>
|
||||
<button onClick={handleModalCloseClick}>
|
||||
<i
|
||||
style={{ fontSize: 25 }}
|
||||
className="fa fa-times-circle"
|
||||
aria-hidden="true"
|
||||
></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{isModal && (
|
||||
<AppendFormInForm
|
||||
valueKey={"objectId"}
|
||||
displayKey={"Name"}
|
||||
details={handleNewDetails}
|
||||
closePopup={handleModalCloseClick}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SignersInput;
|
||||
@@ -0,0 +1,2 @@
|
||||
export const contactCls = "contracts_Contactbook"
|
||||
export const templateCls = "contracts_Template"
|
||||
@@ -1,7 +1,9 @@
|
||||
export default function reportJson(id) {
|
||||
// console.log("json ", json);
|
||||
const head = ["Sr.No", "Name", "Note", "Folder", "File", "Owner", "Signers"];
|
||||
const contactbook = ["Sr.No", "Name", "Email", "Phone"];
|
||||
const head = ["Sr.No", "Title", "Note", "Folder", "File", "Owner", "Signers"];
|
||||
const contactbook = ["Sr.No", "Title", "Email", "Phone"];
|
||||
const dashboardReportHead = ["Title", "File", "Owner", "Signers"];
|
||||
|
||||
switch (id) {
|
||||
// draft documents report
|
||||
case "ByHuevtCFY":
|
||||
@@ -103,7 +105,7 @@ export default function reportJson(id) {
|
||||
case "d9k3UfYHBc":
|
||||
return {
|
||||
reportName: "Recently sent for signatures",
|
||||
heading: head,
|
||||
heading: dashboardReportHead,
|
||||
actions: [
|
||||
{
|
||||
btnLabel: "View",
|
||||
@@ -119,7 +121,7 @@ export default function reportJson(id) {
|
||||
case "5Go51Q7T8r":
|
||||
return {
|
||||
reportName: "Recent signature requests",
|
||||
heading: head,
|
||||
heading: dashboardReportHead,
|
||||
actions: [
|
||||
{
|
||||
btnLabel: "Sign",
|
||||
@@ -135,7 +137,7 @@ export default function reportJson(id) {
|
||||
case "kC5mfynCi4":
|
||||
return {
|
||||
reportName: "Drafts",
|
||||
heading: head,
|
||||
heading: ["Title", "Note", "Folder", "File", "Owner", "Signers"],
|
||||
actions: [
|
||||
{
|
||||
btnLabel: "sign",
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
import React from "react";
|
||||
|
||||
const Alert = ({ children, type }) => {
|
||||
const textcolor = type ? theme(type) : theme();
|
||||
function theme(color) {
|
||||
switch (color) {
|
||||
case "success":
|
||||
return "border-[#c3e6cb] bg-[#d4edda] text-[#155724]";
|
||||
case "info":
|
||||
return "border-[#adcdeb] bg-[#c1daf0] text-[#153756]";
|
||||
case "danger":
|
||||
return "border-[#f0a8a8] bg-[#f4bebe] text-[#c42121]";
|
||||
default:
|
||||
return "border-[#d6d6d6] bg-[#d9d9d9] text-[#575757]";
|
||||
}
|
||||
}
|
||||
return (
|
||||
<>
|
||||
{children && (
|
||||
<div
|
||||
className={`z-40 fixed top-20 left-1/2 transform -translate-x-1/2 border-[1px] text-sm ${textcolor} rounded py-[.75rem] px-[1.25rem] `}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Alert;
|
||||
@@ -135,7 +135,9 @@ const ReportTable = ({
|
||||
{currentLists.map((item, index) =>
|
||||
ReportName === "Contactbook" ? (
|
||||
<tr className="border-y-[1px]" key={index}>
|
||||
<td className="px-4 py-2">{index + 1}</td>
|
||||
{heading.includes("Sr.No") && (
|
||||
<td className="px-4 py-2">{index + 1}</td>
|
||||
)}
|
||||
<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>
|
||||
@@ -179,12 +181,18 @@ const ReportTable = ({
|
||||
</tr>
|
||||
) : (
|
||||
<tr className="border-y-[1px]" key={index}>
|
||||
<td className="px-4 py-2">{index + 1}</td>
|
||||
{heading.includes("Sr.No") && (
|
||||
<td className="px-4 py-2">{index + 1}</td>
|
||||
)}
|
||||
<td className="px-4 py-2 font-semibold">{item?.Name} </td>
|
||||
<td className="px-4 py-2">{item?.Note || "-"}</td>
|
||||
<td className="px-4 py-2">
|
||||
{item?.Folder?.Name || "OpenSignDrive"}
|
||||
</td>
|
||||
{heading.includes("Note") && (
|
||||
<td className="px-4 py-2">{item?.Note || "-"}</td>
|
||||
)}
|
||||
{heading.includes("Folder") && (
|
||||
<td className="px-4 py-2">
|
||||
{item?.Folder?.Name || "OpenSignDrive"}
|
||||
</td>
|
||||
)}
|
||||
<td className="px-4 py-2">
|
||||
<a
|
||||
target="_blank"
|
||||
@@ -235,7 +243,6 @@ const ReportTable = ({
|
||||
{act?.btnLabel ? act.btnLabel : "view"}
|
||||
</span>
|
||||
</button>
|
||||
// )
|
||||
))}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import React, { useState } from "react";
|
||||
|
||||
const Modal = ({ children, Title }) => {
|
||||
const [isOpen, SetIsOpen] = useState(false);
|
||||
return (
|
||||
<>
|
||||
{children && (
|
||||
<div
|
||||
className={`fixed top-20 left-1/2 transform -translate-x-1/2 border-[1px] text-sm bg-white rounded `}
|
||||
>
|
||||
<div className="flex justify-between items-center py-[.75rem] px-[1.25rem] ">
|
||||
<div className="font-semibold text-xl text-black">{Title}</div>
|
||||
<div
|
||||
onClick={() => SetIsOpen()}
|
||||
className="px-2 py-1 bg-gray-400 rounded cursor-pointer"
|
||||
>
|
||||
<i className="fa-solid fa-xmark"></i>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
{isOpen && <div>{children}</div>}
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Modal;
|
||||
@@ -0,0 +1,304 @@
|
||||
import React, { useState } from "react";
|
||||
import sanitizeFileName from "./sanitizeFileName";
|
||||
import Parse from "parse";
|
||||
import DropboxChooser from "../components/fields/DropboxChoose";
|
||||
import Alert from "./Alert";
|
||||
import SelectFolder from "../components/fields/SelectFolder";
|
||||
import SignersInput from "../components/fields/SignersInput";
|
||||
import Title from "../components/Title";
|
||||
const TemplateForm = () => {
|
||||
const [signers, setSigners] = useState([]);
|
||||
const [folder, setFolder] = useState({ ObjectId: "", Name: "" });
|
||||
const [formData, setFormData] = useState({
|
||||
Name: "",
|
||||
Description: "",
|
||||
Note: ""
|
||||
});
|
||||
const [fileupload, setFileUpload] = useState([]);
|
||||
const [fileload, setfileload] = useState(false);
|
||||
const [percentage, setpercentage] = useState(0);
|
||||
const [isAlert, setIsAlert] = useState(false);
|
||||
const handleStrInput = (e) => {
|
||||
setFormData({ ...formData, [e.target.name]: e.target.value });
|
||||
};
|
||||
|
||||
const handleFileInput = (e) => {
|
||||
setpercentage(0);
|
||||
try {
|
||||
let files = e.target.files;
|
||||
if (typeof files[0] !== "undefined") {
|
||||
const mb = Math.round(files[0].bytes / Math.pow(1024, 2));
|
||||
if (mb > 10) {
|
||||
alert(
|
||||
`The selected file size is too large. Please select a file less than ${Math.round(
|
||||
10
|
||||
)} MB`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
handleFileUpload(files[0]);
|
||||
} else {
|
||||
alert("Please select file.");
|
||||
return false;
|
||||
}
|
||||
} catch (error) {
|
||||
alert(error.message);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const handleFileUpload = async (file) => {
|
||||
Parse.serverURL = process.env.REACT_APP_SERVERURL;
|
||||
Parse.initialize(process.env.REACT_APP_APPID);
|
||||
setfileload(true);
|
||||
const fileName = file.name;
|
||||
const name = sanitizeFileName(fileName);
|
||||
const pdfFile = file;
|
||||
const parseFile = new Parse.File(name, pdfFile);
|
||||
|
||||
try {
|
||||
const response = await parseFile.save({
|
||||
progress: (progressValue, loaded, total, { type }) => {
|
||||
if (type === "upload" && progressValue !== null) {
|
||||
const percentCompleted = Math.round((loaded * 100) / total);
|
||||
setpercentage(percentCompleted);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// The response object will contain information about the uploaded file
|
||||
// You can access the URL of the uploaded file using response.url()
|
||||
setFileUpload(response.url());
|
||||
setfileload(false);
|
||||
if (response.url()) {
|
||||
return response.url();
|
||||
}
|
||||
} catch (error) {
|
||||
setfileload(false);
|
||||
setpercentage(0);
|
||||
console.error("Error uploading file:", error);
|
||||
}
|
||||
};
|
||||
|
||||
const dropboxSuccess = async (files) => {
|
||||
setfileload(true);
|
||||
const file = files[0];
|
||||
const url = file.link;
|
||||
const mb = Math.round(file.bytes / Math.pow(1024, 2));
|
||||
|
||||
if (mb > 10) {
|
||||
setTimeout(() => {
|
||||
alert(
|
||||
`The selected file size is too large. Please select a file less than 10 MB`
|
||||
);
|
||||
}, 500);
|
||||
return;
|
||||
} else {
|
||||
const name = sanitizeFileName(file.name);
|
||||
|
||||
const parseFile = new Parse.File(name, { uri: url });
|
||||
|
||||
try {
|
||||
const response = await parseFile.save({
|
||||
progress: (progressValue, loaded, total, { type }) => {
|
||||
if (type === "upload" && progressValue !== null) {
|
||||
const percentCompleted = Math.round((loaded * 100) / total);
|
||||
setpercentage(percentCompleted);
|
||||
}
|
||||
}
|
||||
});
|
||||
setFileUpload(response.url());
|
||||
setfileload(false);
|
||||
|
||||
if (response.url()) {
|
||||
return response.url();
|
||||
}
|
||||
} catch (error) {
|
||||
setfileload(false);
|
||||
setpercentage(0);
|
||||
console.error("Error uploading file:", error);
|
||||
}
|
||||
}
|
||||
};
|
||||
const dropboxCancel = async () => {};
|
||||
const handleSubmit = async (e) => {
|
||||
e.preventDefault();
|
||||
try {
|
||||
const currentUser = Parse.User.current();
|
||||
const template = new Parse.Object("contracts_Template");
|
||||
Object.entries(formData).forEach((item) =>
|
||||
template.set(item[0], item[1])
|
||||
);
|
||||
template.set("URL", fileupload);
|
||||
template.set("CreatedBy", Parse.User.createWithoutData(currentUser.id));
|
||||
if (folder && folder.ObjectId) {
|
||||
template.set("Folder", {
|
||||
__type: "Pointer",
|
||||
className: "contracts_Template",
|
||||
objectId: folder.ObjectId
|
||||
});
|
||||
}
|
||||
if (signers && signers.length > 0) {
|
||||
template.set("Signers", signers);
|
||||
}
|
||||
const res = await template.save();
|
||||
if (res) {
|
||||
setIsAlert(true);
|
||||
setTimeout(() => {
|
||||
setIsAlert(false);
|
||||
}, 1000);
|
||||
setSigners([]);
|
||||
setFolder({ ObjectId: "", Name: "" });
|
||||
setFormData({
|
||||
Name: "",
|
||||
Description: "",
|
||||
Note: ""
|
||||
});
|
||||
setFileUpload([]);
|
||||
setpercentage(0);
|
||||
}
|
||||
} catch (err) {
|
||||
console.log("err ", err);
|
||||
setIsAlert(true);
|
||||
}
|
||||
};
|
||||
|
||||
const handleFolder = (data) => {
|
||||
setFolder(data);
|
||||
};
|
||||
const handleSigners = (data) => {
|
||||
if (data && data.length > 0) {
|
||||
const updateSigners = data.map((x) => ({
|
||||
__type: "Pointer",
|
||||
className: "contracts_Contactbook",
|
||||
objectId: x
|
||||
}));
|
||||
setSigners(updateSigners);
|
||||
}
|
||||
};
|
||||
|
||||
const handleReset = () => {
|
||||
setSigners([]);
|
||||
setFolder({ ObjectId: "", Name: "" });
|
||||
setFormData({
|
||||
Name: "",
|
||||
Description: "",
|
||||
Note: ""
|
||||
});
|
||||
setFileUpload([]);
|
||||
setpercentage(0);
|
||||
};
|
||||
return (
|
||||
<div className="shadow-md rounded my-2 p-3 bg-[#ffffff] md:border-[1px] md:border-gray-600/50">
|
||||
<Title title="New Template" />
|
||||
{isAlert && <Alert type="success">Template created successfully!</Alert>}
|
||||
<form onSubmit={handleSubmit}>
|
||||
<h1 className="text-[20px] font-semibold mb-4">New Template</h1>
|
||||
{fileload && (
|
||||
<div className="flex items-center gap-x-2">
|
||||
<div className="h-2 rounded-full w-[200px] md:w-[400px] bg-gray-200">
|
||||
<div
|
||||
className="h-2 rounded-full bg-blue-500"
|
||||
style={{ width: `${percentage}%` }}
|
||||
></div>
|
||||
</div>
|
||||
<span className="text-black text-sm">{percentage}%</span>
|
||||
</div>
|
||||
)}
|
||||
<div className="text-xs">
|
||||
<label className="block">
|
||||
File<span className="text-red-500 text-[13px]">*</span>
|
||||
</label>
|
||||
{fileupload.length > 0 ? (
|
||||
<div className="flex gap-2 justify-center items-center">
|
||||
<div className="flex justify-between items-center px-2 py-2 w-full font-bold rounded border-[1px] border-[#ccc] text-gray-500 bg-white text-[13px]">
|
||||
<div className="break-all">
|
||||
file selected : {fileupload?.split("/")[3]?.split("_")[1]}
|
||||
</div>
|
||||
<div
|
||||
onClick={() => {
|
||||
setFileUpload([]);
|
||||
}}
|
||||
className="cursor-pointer px-[10px] text-[20px] font-bold bg-white text-red-500"
|
||||
>
|
||||
<i className="fa-solid fa-xmark"></i>
|
||||
</div>
|
||||
</div>
|
||||
{process.env.DROPBOX_APP_KEY && (
|
||||
<DropboxChooser
|
||||
onSuccess={dropboxSuccess}
|
||||
onCancel={dropboxCancel}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex gap-2 justify-center items-center">
|
||||
<input
|
||||
type="file"
|
||||
className="bg-white px-2 py-1.5 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
|
||||
onChange={(e) => handleFileInput(e)}
|
||||
accept="application/pdf,application/vnd.ms-excel"
|
||||
required
|
||||
/>
|
||||
{process.env.DROPBOX_APP_KEY && (
|
||||
<DropboxChooser
|
||||
onSuccess={dropboxSuccess}
|
||||
onCancel={dropboxCancel}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="text-xs mt-2">
|
||||
<label className="block">
|
||||
Title<span className="text-red-500 text-[13px]">*</span>
|
||||
</label>
|
||||
<input
|
||||
name="Name"
|
||||
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
|
||||
value={formData.Name}
|
||||
onChange={(e) => handleStrInput(e)}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div className="text-xs mt-2">
|
||||
<label className="block">Note</label>
|
||||
<input
|
||||
name="Note"
|
||||
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
|
||||
value={formData.Note}
|
||||
onChange={(e) => handleStrInput(e)}
|
||||
/>
|
||||
</div>
|
||||
<div className="text-xs mt-2">
|
||||
<label className="block">Description</label>
|
||||
<input
|
||||
name="Description"
|
||||
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
|
||||
value={formData.Description}
|
||||
onChange={(e) => handleStrInput(e)}
|
||||
/>
|
||||
</div>
|
||||
<SignersInput onChange={handleSigners} />
|
||||
<SelectFolder onSuccess={handleFolder} />
|
||||
<div className="flex items-center mt-3 gap-2 text-white">
|
||||
<button
|
||||
className="px-2 py-2 uppercase rounded shadow-md bg-sky-300 text-xs font-semibold"
|
||||
type="submit"
|
||||
>
|
||||
Submit
|
||||
</button>
|
||||
<div
|
||||
className="px-2 py-2 uppercase rounded shadow-md bg-blue-500 text-xs font-semibold"
|
||||
onClick={() => handleReset()}
|
||||
>
|
||||
Reset
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TemplateForm;
|
||||
@@ -25,6 +25,7 @@ import TreeWidget from "../components/TreeWidget";
|
||||
import parse from "html-react-parser";
|
||||
import Title from "../components/Title";
|
||||
import { formJson } from "../json/FormJson";
|
||||
import TemplateForm from "../primitives/TemplateForm";
|
||||
const widget = {
|
||||
TimeWidget: TimeWidget
|
||||
};
|
||||
@@ -41,15 +42,19 @@ const fields = () => {
|
||||
function FormBuilderFn(props) {
|
||||
const { id } = useParams();
|
||||
const navigate = useNavigate();
|
||||
return (
|
||||
<FormBuilder
|
||||
removeState={props.removeState}
|
||||
removeLevel2State={props.removeLevel2State}
|
||||
removeLevel3State={props.removeLevel3State}
|
||||
id={id}
|
||||
navigate={navigate}
|
||||
/>
|
||||
);
|
||||
if (id === "template") {
|
||||
return <TemplateForm />;
|
||||
} else {
|
||||
return (
|
||||
<FormBuilder
|
||||
removeState={props.removeState}
|
||||
removeLevel2State={props.removeLevel2State}
|
||||
removeLevel3State={props.removeLevel3State}
|
||||
id={id}
|
||||
navigate={navigate}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
class FormBuilder extends Component {
|
||||
state = {
|
||||
|
||||
@@ -17,6 +17,7 @@ import getUserDetails from './parsefunction/getUserDetails.js';
|
||||
import getDocument from './parsefunction/getDocument.js';
|
||||
import getDrive from './parsefunction/getDrive.js';
|
||||
import getReport from './parsefunction/getReport.js';
|
||||
import TemplateAfterSave from './parsefunction/TemplateAfterSave.js';
|
||||
|
||||
Parse.Cloud.define('AddUserToRole', addUserToGroups);
|
||||
Parse.Cloud.define('UserGroups', getUserGroups);
|
||||
@@ -26,9 +27,6 @@ Parse.Cloud.define('googlesign', GoogleSign);
|
||||
Parse.Cloud.define('zohodetails', ZohoDetails);
|
||||
Parse.Cloud.define('usersignup', usersignup);
|
||||
Parse.Cloud.define('facebooksign', FacebookSign);
|
||||
Parse.Cloud.afterSave('contracts_Document', DocumentAftersave);
|
||||
Parse.Cloud.afterSave('contracts_Contactbook', ContactbookAftersave);
|
||||
Parse.Cloud.afterSave('contracts_Users', ContractUsersAftersave);
|
||||
Parse.Cloud.define('SendOTPMailV1', sendMailOTPv1);
|
||||
Parse.Cloud.define('sendmail', SendMailv1);
|
||||
Parse.Cloud.define('AuthLoginAsMail', AuthLoginAsMail);
|
||||
@@ -36,4 +34,8 @@ Parse.Cloud.define('getUserId', getUserId);
|
||||
Parse.Cloud.define('getUserDetails', getUserDetails);
|
||||
Parse.Cloud.define('getDocument', getDocument);
|
||||
Parse.Cloud.define('getDrive', getDrive)
|
||||
Parse.Cloud.define('getReport', getReport)
|
||||
Parse.Cloud.define('getReport', getReport)
|
||||
Parse.Cloud.afterSave('contracts_Document', DocumentAftersave);
|
||||
Parse.Cloud.afterSave('contracts_Contactbook', ContactbookAftersave);
|
||||
Parse.Cloud.afterSave('contracts_Users', ContractUsersAftersave);
|
||||
Parse.Cloud.afterSave("contracts_Template", TemplateAfterSave)
|
||||
@@ -0,0 +1,83 @@
|
||||
export default async function TemplateAfterSave(request) {
|
||||
try {
|
||||
if (!request.original) {
|
||||
console.log('new entry is insert in contracts_Template');
|
||||
// update acl of New Document If There are signers present in array
|
||||
const signers = request.object.get('Signers');
|
||||
|
||||
if (signers && signers.length > 0) {
|
||||
await updateAclDoc(request.object.id);
|
||||
} else {
|
||||
await updateSelfDoc(request.object.id);
|
||||
}
|
||||
} else {
|
||||
if (request.user) {
|
||||
const signers = request.object.get('Signers');
|
||||
if (signers && signers.length > 0) {
|
||||
await updateAclDoc(request.object.id);
|
||||
} else {
|
||||
await updateSelfDoc(request.object.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.log('err in aftersave of contracts_Template');
|
||||
console.log(err);
|
||||
}
|
||||
|
||||
async function updateAclDoc(objId) {
|
||||
// console.log("In side updateAclDoc func")
|
||||
// console.log(objId)
|
||||
const Query = new Parse.Query('contracts_Template');
|
||||
Query.include('Signers');
|
||||
const updateACL = await Query.get(objId, { useMasterKey: true });
|
||||
const res = JSON.parse(JSON.stringify(updateACL));
|
||||
// console.log("res");
|
||||
// console.log(JSON.stringify(res));
|
||||
const UsersPtr = res.Signers.map(item => item.UserId);
|
||||
|
||||
if (res.Signers[0].ExtUserPtr) {
|
||||
const ExtUserSigners = res.Signers.map(item => {
|
||||
return {
|
||||
__type: 'Pointer',
|
||||
className: 'contracts_Users',
|
||||
objectId: item.ExtUserPtr.objectId,
|
||||
};
|
||||
});
|
||||
updateACL.set('Signers', ExtUserSigners);
|
||||
}
|
||||
|
||||
// console.log("UsersPtr")
|
||||
// console.log(JSON.stringify(UsersPtr))
|
||||
const newACL = new Parse.ACL();
|
||||
newACL.setPublicReadAccess(false);
|
||||
newACL.setPublicWriteAccess(false);
|
||||
newACL.setReadAccess(request.user, true);
|
||||
newACL.setWriteAccess(request.user, true);
|
||||
|
||||
UsersPtr.forEach(x => {
|
||||
newACL.setReadAccess(x.objectId, true);
|
||||
newACL.setWriteAccess(x.objectId, true);
|
||||
});
|
||||
|
||||
updateACL.setACL(newACL);
|
||||
updateACL.save(null, { useMasterKey: true });
|
||||
}
|
||||
|
||||
async function updateSelfDoc(objId) {
|
||||
// console.log("Inside updateSelfDoc func")
|
||||
|
||||
const Query = new Parse.Query('contracts_Template');
|
||||
const updateACL = await Query.get(objId, { useMasterKey: true });
|
||||
// const res = JSON.parse(JSON.stringify(updateACL));
|
||||
// console.log("res");
|
||||
// console.log(JSON.stringify(res));
|
||||
const newACL = new Parse.ACL();
|
||||
newACL.setPublicReadAccess(false);
|
||||
newACL.setPublicWriteAccess(false);
|
||||
newACL.setReadAccess(request.user, true);
|
||||
newACL.setWriteAccess(request.user, true);
|
||||
updateACL.setACL(newACL);
|
||||
updateACL.save(null, { useMasterKey: true });
|
||||
}
|
||||
}
|
||||
@@ -154,7 +154,7 @@ export default function reportJson(id, userId) {
|
||||
$gt: { __type: 'Date', iso: new Date().toISOString() },
|
||||
},
|
||||
},
|
||||
keys: ['Name', 'Note', 'Folder.Name', 'URL', 'ExtUserPtr.Name', 'Signers.Name'],
|
||||
keys: ['Name', 'Folder.Name', 'URL', 'ExtUserPtr.Name', 'Signers.Name'],
|
||||
};
|
||||
// Recent signature requests report show on dashboard
|
||||
case '5Go51Q7T8r':
|
||||
@@ -169,16 +169,7 @@ export default function reportJson(id, userId) {
|
||||
},
|
||||
Placeholders: { $ne: null },
|
||||
},
|
||||
keys: [
|
||||
'Name',
|
||||
'Note',
|
||||
'Folder.Name',
|
||||
'URL',
|
||||
'ExtUserPtr.Name',
|
||||
'Signers.Name',
|
||||
'Signers.UserId',
|
||||
'AuditTrail',
|
||||
],
|
||||
keys: ['Name', 'URL', 'ExtUserPtr.Name', 'Signers.Name', 'Signers.UserId', 'AuditTrail'],
|
||||
};
|
||||
// Drafts report show on dashboard
|
||||
case 'kC5mfynCi4':
|
||||
|
||||
@@ -39,6 +39,14 @@ exports.up = async Parse => {
|
||||
description: '',
|
||||
objectId: '8mZzFxbG1z',
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-file-signature',
|
||||
title: 'New template',
|
||||
target: '_self',
|
||||
pageType: 'form',
|
||||
description: '',
|
||||
objectId: 'template',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
*
|
||||
* @param {Parse} Parse
|
||||
*/
|
||||
exports.up = async Parse => {
|
||||
const className = 'contracts_Template';
|
||||
const schema = new Parse.Schema(className);
|
||||
|
||||
schema.addString('Name');
|
||||
schema.addString('URL');
|
||||
schema.addString('Note');
|
||||
schema.addString('Description');
|
||||
schema.addArray('Signers');
|
||||
schema.addBoolean('IsArchive');
|
||||
schema.addArray('Placeholders');
|
||||
schema.addPointer('Folder', 'contracts_Template');
|
||||
schema.addString('Type');
|
||||
schema.addPointer('CreatedBy', '_User');
|
||||
schema.addPointer('ExtUserPtr', 'contracts_Users');
|
||||
schema.addBoolean('EnablePhoneOTP')
|
||||
schema.addBoolean('EnableEmailOTP')
|
||||
schema.addBoolean('SendinOrder')
|
||||
schema.addBoolean('SentToOthers')
|
||||
schema.addBoolean('AutomaticReminders')
|
||||
|
||||
|
||||
|
||||
return schema.save();
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {Parse} Parse
|
||||
*/
|
||||
exports.down = async Parse => {
|
||||
const className = 'contracts_Template';
|
||||
const schema = new Parse.Schema(className);
|
||||
|
||||
return schema.purge().then(() => schema.delete());
|
||||
};
|
||||
@@ -69,7 +69,9 @@ if (process.env.SMTP_ENABLE) {
|
||||
export const config = {
|
||||
databaseURI:
|
||||
process.env.DATABASE_URI || process.env.MONGODB_URI || 'mongodb://localhost:27017/dev',
|
||||
cloud: process.env.CLOUD || __dirname + '/cloud/main.js',
|
||||
cloud: function () {
|
||||
import('./cloud/main.js');
|
||||
},
|
||||
appId: process.env.APP_ID || 'myAppId',
|
||||
masterKey: process.env.MASTER_KEY || '', //Add your master key here. Keep it secret!
|
||||
masterKeyIps: ['0.0.0.0/0', '::1'], // '::1'
|
||||
|
||||
Reference in New Issue
Block a user