Merge pull request #507 from OpenSignLabs/staging

v1.3.2-beta
This commit is contained in:
Amol
2024-03-19 16:03:24 +05:30
committed by GitHub
26 changed files with 1032 additions and 140 deletions
+1 -1
View File
@@ -20,7 +20,7 @@ appName=open_sign_server
# A 12 character long random secret key that allows access to all the data. It is used in Parse dashboard config to view all the data in the database.
MASTER_KEY=XnAadwKxxByMr
# Mongodb URI to connect to
MONGODB_URI=mongodb://host.docker.internal:27017/OpenSignDB
MONGODB_URI=mongodb://localhost:27017/OpenSignDB
# Path on which APIs should be mounted. Do not change this. This variable shall be removed & value hardcoded in the source code in coming versions.
PARSE_MOUNT=/app
# Set it to the URL from where APIs will be accessible to the NodeJS functions, for local development it should be localhost:3000/api/app (use your local port number instead)
+3
View File
@@ -14,6 +14,9 @@ RUN npm install
COPY apps/OpenSign/ .
COPY apps/OpenSign/.husky .
# build
RUN npm run build
# Make port 3000 available to the world outside this container
EXPOSE 3000
@@ -0,0 +1,47 @@
import React from "react";
import "../../styles/loader.css";
import { useNavigate } from "react-router-dom";
import { openInNewTab } from "../../constant/Utils";
const DashboardButton = (props) => {
const navigate = useNavigate();
function openReport() {
if (props.Data && props.Data.Redirect_type) {
const Redirect_type = props.Data.Redirect_type;
const id = props.Data.Redirect_id;
if (Redirect_type === "Form") {
navigate(`/form/${id}`);
} else if (Redirect_type === "Report") {
navigate(`/report/${id}`);
} else if (Redirect_type === "Url") {
openInNewTab(id);
}
}
}
return (
<div
onClick={() => openReport()}
className={`${
props.Data && props.Data.Redirect_type
? "cursor-pointer"
: "cursor-default"
} w-full px-3 py-2 flex text-white rounded-md shadow overflow-hidden`}
>
<div className="flex items-center justify-start gap-5">
<span className="rounded-full bg-black bg-opacity-20 w-[60px] h-[60px] self-start flex justify-center items-center">
<i
className={`${
props.Icon ? props.Icon : "fa fa-solid fa-info"
} text-[25px] lg:text-[30px]`}
></i>
</span>
<div className="">
<div className="text-base lg:text-lg text-black"> {props.Label}</div>
</div>
</div>
</div>
);
};
export default DashboardButton;
@@ -1,14 +1,51 @@
import React, { Suspense, lazy } from "react";
const DashboardButton = lazy(() => import("./DashboardButton"));
const DashboardCard = lazy(() => import("./DashboardCard"));
const DashboardReport = lazy(() => import("./DashboardReport"));
const buttonList = [
{
label: "Sign yourself",
redirectId: "sHAnZphf69",
redirectType: "Form"
},
{
label: "Request signature",
redirectId: "8mZzFxbG1z",
redirectType: "Form"
}
];
const GetDashboard = (props) => {
const Button = ({ label, redirectId, redirectType }) => (
<div className={"bg-white rounded-md shadow w-full"}>
<Suspense
fallback={
<div style={{ height: "300px" }}>
<div
style={{
marginLeft: "45%",
marginTop: "150px",
fontSize: "45px",
color: "#3dd3e0"
}}
className="loader-37"
></div>
</div>
}
>
<DashboardButton
Icon={"fa-solid fa-plus"}
Label={label}
Data={{ Redirect_type: redirectType, Redirect_id: redirectId }}
/>
</Suspense>
</div>
);
const renderSwitchWithTour = (col) => {
switch (col.widget.type) {
case "Card":
return (
<div
className={"bg-[#2ed8b6] rounded-md shadow mb-4 md:mb-0"}
className={"bg-[#2ed8b6] rounded-md shadow mb-3 md:mb-0"}
data-tut={col.widget.data.tourSection}
style={{ background: col.widget.bgColor }}
>
@@ -42,7 +79,7 @@ const GetDashboard = (props) => {
return (
<div data-tut={col.widget.data.tourSection}>
<Suspense fallback={<div>please wait</div>}>
<div className="mb-4 md:mb-0">
<div className="mb-3 md:mb-0">
<DashboardReport Record={col.widget} />
</div>
</Suspense>
@@ -58,7 +95,7 @@ const GetDashboard = (props) => {
case "Card":
return (
<div
className={"bg-[#2ed8b6] rounded-md shadow mb-4 md:mb-0"}
className={"bg-[#2ed8b6] rounded-md shadow mb-3 md:mb-0"}
style={{ background: col.widget.bgColor }}
>
<Suspense fallback={<div>please wait</div>}>
@@ -76,7 +113,7 @@ const GetDashboard = (props) => {
case "report": {
return (
<Suspense fallback={<div>please wait</div>}>
<div className="mb-4 md:mb-0">
<div className="mb-3 md:mb-0">
<DashboardReport Record={col.widget} />
</div>
</Suspense>
@@ -88,6 +125,21 @@ const GetDashboard = (props) => {
};
return (
<div>
<div className="mb-3">
<div
data-tut={"tourbutton"}
className="flex flex-col md:flex-row gap-6 md:gap-8"
>
{buttonList.map((btn) => (
<Button
key={btn.label}
label={btn.label}
redirectType={btn.redirectType}
redirectId={btn.redirectId}
/>
))}
</div>
</div>
{props.dashboard.map((val, key) => (
<div key={"a" + key} className="row">
{val.columns.map((col, i) =>
@@ -377,7 +377,7 @@ function DropdownWidgetOption(props) {
/>
<label className="ml-1" htmlFor="ishidelabel">
Hide label
Hide labels
</label>
</div>
</div>
@@ -215,7 +215,8 @@ function Placeholder(props) {
"company",
"job title",
"date",
"email"
"email",
textWidget
].includes(props.pos.type);
if (widgetTypeExist) {
@@ -594,7 +595,7 @@ function Placeholder(props) {
disableDragging={
props.isNeedSign
? true
: props.isPlaceholder && props.pos.type !== "date"
: props.isPlaceholder && ![textWidget].includes(props.pos.type)
? false
: !isDraggingEnabled
}
@@ -652,8 +653,18 @@ function Placeholder(props) {
style={{
left: props.xPos(props.pos, props.isSignYourself),
top: props.yPos(props.pos, props.isSignYourself),
width: "auto", //props.posWidth(props.pos, props.isSignYourself),
width:
props.pos.type === radioButtonWidget ||
props.pos.type === "checkbox"
? "auto"
: props.posWidth(props.pos, props.isSignYourself),
// "auto", //props.posWidth(props.pos, props.isSignYourself),
// height: props.posHeight(props.pos, props.isSignYourself),
height:
props.pos.type === radioButtonWidget ||
props.pos.type === "checkbox"
? "auto"
: props.posHeight(props.pos, props.isSignYourself),
zIndex: "10"
}}
onTouchEnd={() => handleOnClickPlaceholder()}
@@ -4,7 +4,8 @@ import {
defaultWidthHeight,
isMobile,
radioButtonWidget,
resizeBorderExtraWidth
resizeBorderExtraWidth,
textWidget
} from "../../constant/Utils";
function PlaceholderBorder(props) {
const getResizeBorderExtraWidth = resizeBorderExtraWidth();
@@ -31,7 +32,10 @@ function PlaceholderBorder(props) {
};
return (
<div
onMouseEnter={!isMobile && props?.setDraggingEnabled(true)}
onMouseEnter={() => !isMobile && props?.setDraggingEnabled(true)}
onTouchEnd={() =>
props.pos.type === textWidget && props?.setDraggingEnabled(true)
}
className="borderResize"
style={{
borderColor: themeColor,
@@ -2,6 +2,7 @@ import React, { useEffect, useState, forwardRef, useRef } from "react";
import {
getMonth,
getYear,
isMobile,
onChangeInput,
radioButtonWidget,
range,
@@ -741,6 +742,7 @@ function PlaceholderType(props) {
placeholder="Enter label"
rows={1}
value={textValue}
onBlur={handleInputBlur}
onChange={(e) => {
setTextValue(e.target.value);
onChangeInput(
@@ -753,7 +755,11 @@ function PlaceholderType(props) {
false
);
}}
className="labelTextArea"
className={
isMobile
? "labelTextArea labelWidthMobile"
: "labelTextArea labelWidthDesktop"
}
style={{ whiteSpace: "pre-wrap" }}
cols="50"
/>
@@ -239,8 +239,8 @@ function WidgetComponent({
const updateWidgets = isSignYourself
? filterWidgets
: isTemplateFlow
? textWidgetData
: widget;
? textWidgetData
: widget;
return (
<>
@@ -264,11 +264,7 @@ function WidgetComponent({
alignItems: "center",
justifyContent: "center"
}}
onClick={() => {
// if (signersdata?.length) {
handleModal();
// }
}}
onClick={() => handleModal()}
>
<span
style={{
@@ -346,7 +342,7 @@ function WidgetComponent({
display: "flex",
overflowX: "scroll",
whiteSpace: "nowrap",
padding: "10px"
padding: "10px 5px 10px 1px"
}}
>
<WidgetList
@@ -4,7 +4,7 @@ import { getWidgetType } from "../../constant/Utils";
function WidgetList(props) {
return props.updateWidgets.map((item, ind) => {
return (
<div key={ind} style={{ marginBottom: "10px" }}>
<div key={ind} style={{ marginBottom: "5px" }}>
<div
className="widgets"
onClick={() => {
@@ -129,18 +129,7 @@ const WidgetNameModal = (props) => {
>
<div style={{ width: "100%", position: "relative" }}>
<input
style={{
padding: "0.5rem 0.75rem",
width: "92%",
borderWidth: "1px",
borderColor: "#d1d5db",
borderTopLeftRadius: "0.375rem",
borderBottomLeftRadius: "0.375rem",
outline: "none",
fontSize: "0.75rem",
position: "relative",
zIndex: 2
}}
className="relative z-20 w-[87%] md:w-[92%] p-2.5 border-[1px] border-[#d1d5db] rounded-l-md outline-none text-xs"
name="textvalidate"
placeholder="Enter custom expression"
value={formdata.textvalidate}
@@ -148,8 +137,7 @@ const WidgetNameModal = (props) => {
// onBlur={() => handleBlurRegex()}
/>
<select
style={{ position: "absolute", left: 0, zIndex: 1 }}
className="addUserInput"
className="validationlist addUserInput"
name="textvalidate"
value={formdata.textvalidate}
onChange={(e) => handleChange(e)}
@@ -93,7 +93,7 @@ const SelectFolder = ({ required, onSuccess, folderCls, isReset }) => {
// `handleSubmit` is used to pass folderPtr to parent component
const handleSubmit = () => {
let url = "Root";
let url = "OpenSign™ Drive";
tabList.forEach((t) => {
url = url + " / " + t.Name;
});
@@ -180,7 +180,9 @@ const SelectFolder = ({ required, onSuccess, folderCls, isReset }) => {
<div className="font-semibold ">
<div className="flex items-center gap-2">
<p>
{selectFolder && selectFolder.Name ? selectFolder.Name : "Root"}
{selectFolder && selectFolder.Name
? selectFolder.Name
: "OpenSign™ Drive"}
</p>
<div className="text-black text-sm" onClick={() => SetIsOpen(true)}>
<i
@@ -207,14 +209,14 @@ const SelectFolder = ({ required, onSuccess, folderCls, isReset }) => {
isOpen={isOpen}
handleClose={handleCancel}
>
<div className="w-full min-w-[300px] md:min-w-[500px] px-3">
<div className="w-full min-w-[300px] md:min-w-[500px] max-w-[500px] px-3">
<div className="py-2 text-[#ac4848] text-[14px] font-[500]">
<span
className="cursor-pointer"
title="Root"
title="OpenSign™ Drive"
onClick={(e) => removeTabListItem(e)}
>
Root /{" "}
OpenSign Drive /{" "}
</span>
{tabList &&
tabList.map((tab, i) => (
+10 -22
View File
@@ -288,26 +288,14 @@ export const getWidgetType = (item, marginLeft) => {
marginLeft: marginLeft && `${marginLeft}px`
}}
>
<div
style={{
display: "flex",
alignItems: "center",
marginLeft: "5px"
}}
>
<i
className="fa-sharp fa-solid fa-grip-vertical"
style={{ color: "#908d8d", fontSize: "13px" }}
></i>
<span
style={{
fontWeight: "400",
fontSize: "15px",
// padding: "3px 20px 0px 20px",
color: "black",
marginLeft: "5px"
}}
>
<div className="flex items-center mr-1">
{!isMobile && (
<i
className="fa-sharp fa-solid fa-grip-vertical"
style={{ color: "#908d8d", fontSize: "13px", marginLeft: 4 }}
></i>
)}
<span className=" font-[400] text-[15px] text-black ml-[5px]">
{item.type}
</span>
</div>
@@ -1090,8 +1078,8 @@ export const multiSignEmbed = async (
position.type === radioButtonWidget
? 10
: position.type === "checkbox"
? 10
: newUpdateHeight;
? 10
: newUpdateHeight;
const newHeight = ind ? (ind > 0 ? widgetHeight : 0) : widgetHeight;
if (signyourself) {
+6
View File
@@ -94,6 +94,12 @@ const HomeLayout = () => {
position: "top"
// style: { backgroundColor: "#abd4d2" },
},
{
selector: '[data-tut="tourbutton"]',
content: `To upload documents for self-signing or to request others signatures, simply select the respective buttons.`,
position: "top"
// style: { backgroundColor: "#abd4d2" },
},
...resArr,
{
selector: '[data-tut="reactourLast"]',
+10 -9
View File
@@ -28,6 +28,7 @@ function Form() {
}
const Forms = (props) => {
const maxFileSize = 20;
const navigate = useNavigate();
const [signers, setSigners] = useState([]);
const [folder, setFolder] = useState({ ObjectId: "", Name: "" });
@@ -56,17 +57,17 @@ const Forms = (props) => {
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) {
const mb = Math.round(files[0].size / Math.pow(1024, 2));
if (mb > maxFileSize) {
alert(
`The selected file size is too large. Please select a file less than ${Math.round(
10
)} MB`
`The selected file size is too large. Please select a file less than ${maxFileSize} MB`
);
setFileUpload([]);
e.target.value = "";
return;
} else {
handleFileUpload(files[0]);
}
handleFileUpload(files[0]);
} else {
alert("Please select file.");
return false;
@@ -114,10 +115,10 @@ const Forms = (props) => {
const url = file.link;
const mb = Math.round(file.bytes / Math.pow(1024, 2));
if (mb > 10) {
if (mb > maxFileSize) {
setTimeout(() => {
alert(
`The selected file size is too large. Please select a file less than 10 MB`
`The selected file size is too large. Please select a file less than ${maxFileSize} MB`
);
}, 500);
return;
+1 -1
View File
@@ -988,7 +988,7 @@ function PdfRequestFiles() {
: isDecline.currnt === "YouDeclined"
? "You have declined this document!"
: isDecline.currnt === "another" &&
"You cannot sign this document as it has been declined by one or more person(s)."
"You cannot sign this document as it has been declined by one or more recipient(s)."
}
footerMessage={isDecline.currnt === "Sure"}
declineDoc={declineDoc}
+74 -18
View File
@@ -102,6 +102,10 @@ function PlaceHolderSign() {
const [widgetName, setWidgetName] = useState(false);
const [mailStatus, setMailStatus] = useState("");
const [isCurrUser, setIsCurrUser] = useState(false);
const [isAlreadyPlace, setIsAlreadyPlace] = useState({
status: false,
message: ""
});
const color = [
"#93a3db",
"#e6c3db",
@@ -193,15 +197,49 @@ function PlaceHolderSign() {
//getting document details
const documentData = await contractDocument(documentId);
if (documentData && documentData.length > 0) {
// const alreadyPlaceholder =
// documentData[0].Placeholders && documentData[0].Placeholders;
// if (alreadyPlaceholder && alreadyPlaceholder.length > 0) {
// setIsAlreadyPlace(true);
// }
// setSignersData(documentData[0]);
// setIsSelectId(0);
// setSignerObjId(documentData[0].Signers[0].objectId);
// setContractName(documentData[0].Signers[0].className);
const alreadyPlaceholder = documentData[0]?.SignedUrl;
// Check if document is sent for signing
if (alreadyPlaceholder) {
// Check if the document is completed
const isCompleted =
documentData[0].IsCompleted && documentData[0]?.IsCompleted;
// Get the expiration date of the document
const expireDate = documentData[0].ExpiryDate.iso;
// Check if the document has been declined
const declined =
documentData[0].IsDeclined && documentData[0]?.IsDeclined;
// Get the expiration update date in milliseconds
const expireUpdateDate = new Date(expireDate).getTime();
// Get the current date in milliseconds
const currDate = new Date().getTime();
if (isCompleted) {
// If document is completed
setIsAlreadyPlace({
status: true,
message: "This document has been signed by all Signers."
});
} else if (declined) {
// If document has been declined
setIsAlreadyPlace({
status: true,
message:
"This document has been declined by one or more recipient(s)."
});
} else if (currDate > expireUpdateDate) {
// If document has expired
setIsAlreadyPlace({
status: true,
message: "This Document is no longer available."
});
} else {
// If document is dispatched for signing
setIsAlreadyPlace({
status: true,
message: "The document has already been dispatched for signing."
});
}
}
setPdfDetails(documentData);
if (documentData[0].Signers && documentData[0].Signers.length > 0) {
@@ -317,9 +355,6 @@ function PlaceHolderSign() {
//function for setting position after drop signature button over pdf
const addPositionOfSignature = (item, monitor) => {
if (item && item.text) {
setWidgetName(item.text);
}
getSignerPos(item, monitor);
};
@@ -336,7 +371,6 @@ function PlaceHolderSign() {
let dropData = [];
let placeHolder;
const dragTypeValue = item?.text ? item.text : monitor.type;
if (item === "onclick") {
const dropObj = {
//onclick put placeholder center on pdf
@@ -487,15 +521,11 @@ function PlaceHolderSign() {
setIsCheckbox(true);
} else if (dragTypeValue === radioButtonWidget) {
setIsRadio(true);
} else if (
dragTypeValue !== textWidget &&
dragTypeValue !== "signature"
) {
setIsNameModal(true);
}
setWidgetType(dragTypeValue);
setSignKey(key);
setCurrWidgetsDetails({});
setWidgetName(dragTypeValue);
}
}
};
@@ -1760,7 +1790,33 @@ function PlaceHolderSign() {
</button>
</div>
</ModalUi>
<ModalUi
headerColor={"#dc3545"}
isOpen={isAlreadyPlace.status}
title={"Document Alert"}
showClose={false}
>
<div style={{ height: "100%", padding: 20 }}>
<p>{isAlreadyPlace.message}</p>
<div
style={{
height: "1px",
backgroundColor: "#9f9f9f",
width: "100%",
marginTop: "15px",
marginBottom: "15px"
}}
></div>
<button
onClick={() => handleRecipientSign()}
type="button"
className="finishBtn cancelBtn"
>
View
</button>
</div>
</ModalUi>
<LinkUserModal
handleAddUser={handleAddUser}
isAddUser={isAddUser}
@@ -23,7 +23,6 @@ import {
defaultWidthHeight,
addWidgetOptions,
textInputWidget,
textWidget,
radioButtonWidget
} from "../constant/Utils";
import RenderPdf from "../components/pdf/RenderPdf";
@@ -447,12 +446,7 @@ const TemplatePlaceholder = () => {
setIsCheckbox(true);
} else if (dragTypeValue === radioButtonWidget) {
setIsRadio(true);
} else if (
dragTypeValue !== textWidget &&
dragTypeValue !== "signature"
) {
setIsNameModal(true);
}
}
setCurrWidgetsDetails({});
setWidgetType(dragTypeValue);
setSignKey(key);
+27
View File
@@ -60,6 +60,7 @@
color: #ffffff;
outline: none;
}
/* For classes: bg-[#188ae2] text-sm text-white px-4 py-2 rounded ml-2 shadow focus:outline-none */
.resetbutton {
background-color: #188ae2;
@@ -75,3 +76,29 @@
outline: none;
margin-left: 8px;
}
.validationlist {
position: absolute;
left: 0;
z-index: 1;
appearance: none;
-moz-appearance: "none";
-webkit-appearance: "none";
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAYAAADE6YVjAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAnUlEQVR4nO2QMQrCQBBFX51NbWMp2uox7Gw8h22uYEguIZNKyB0lMIElTNzdGBvdB8PC8Gces5DJ/Cxn4Aa4QM5pbsgncQF6rQYoZ3IFcPey11jByRsaqzYuctqfZo8xki3QBURuRtDpfBQ74GEsaYHN5It8wYFEhgExlj2NniwRhC7qP70gRSRrCN6JZE2BJZJvCEb2QKVvJvMvvAD2WzaK/35kGAAAAABJRU5ErkJggg==");
background-repeat: no-repeat;
background-position: right 0.7rem top 50%;
background-size: 1rem auto;
}
@media (max-width: 375px) {
.validationlist {
background-position: right 0.5rem top 50%;
}
}
@media (min-width:375px) and (max-width: 767px) {
.validationlist {
background-position: right 1rem top 50%;
}
}
+17 -5
View File
@@ -163,7 +163,6 @@
.signatureBtn {
border: 1.5px solid #47a3ad;
border-radius: 3px;
display: flex;
padding: 0px;
@@ -838,10 +837,18 @@ option {
justify-content: flex-start;
}
.labelTextArea {
font-size: 12px;
.labelWidthDesktop {
min-width: 100%;
min-height: 100%;
}
.labelWidthMobile {
width: 100%;
height: 100%;
}
.labelTextArea {
font-size: 12px;
border: 1px solid #007bff;
outline: none;
z-index: 999;
@@ -945,7 +952,7 @@ option {
to prevent sudden quick movement (as the
navigation bar gets a new position at the top of the
page (position:fixed and top:0) */
.stickyHead + .content {
.stickyHead+.content {
padding-top: 60px;
}
@@ -1174,6 +1181,7 @@ option {
font-size: 12px;
margin-left: 5px;
}
.defaultOptions:focus {
outline: none;
}
@@ -1193,6 +1201,10 @@ option {
overflow-y: auto;
}
.signatureBtn {
width: max-content;
}
.dropdownModal {
position: fixed;
top: 50%;
@@ -1222,4 +1234,4 @@ option {
min-width: 78%;
overflow-y: auto;
}
}
}
@@ -165,29 +165,26 @@ export default async function createDocumentwithCoordinate(request, response) {
'Signers',
contact?.map(x => x.contactPtr)
);
let updatePlaceholders = contact.map((signer, index) => {
let updatePlaceholders = contact.map(signer => {
const placeHolder = [];
for (const widget of signer.widgets) {
const pageNumber = widget.page;
const page = placeHolder.find(page => page.pageNumber === pageNumber);
const signOpt = { name: 'signature', status: 'required' };
const widgetData = {
xPosition: widget.x,
yPosition: widget.y,
isStamp: widget.type === 'stamp',
key: randomId(),
isDrag: false,
firstXPos: widget.x,
firstYPos: widget.y,
yBottom: 0,
scale: 1,
isMobile: false,
zIndex: 1,
type: widget.type,
widgetValue: '',
options: widget.type === 'signature' ? signOpt : widget.options,
Width: widget.w,
Height: widget.h,
xPosition: widget.x,
yPosition: widget.y,
};
if (page) {
@@ -123,7 +123,7 @@ export default async function createTemplate(request, response) {
}
return response.json({
objectId: res.id,
url: baseUrl.origin + '/load/signmicroapp/template/' + res.id,
url: baseUrl.origin + '/template/' + res.id,
});
} else {
return response.status(405).json({ error: 'Invalid API Token!' });
@@ -129,23 +129,20 @@ export default async function createTemplatewithCoordinate(request, response) {
for (const widget of signer.widgets) {
const pageNumber = widget.page;
const page = placeHolder.find(page => page.pageNumber === pageNumber);
const signOpt = { name: 'signature', status: 'required' };
const widgetData = {
xPosition: widget.x,
yPosition: widget.y,
isStamp: widget.type === 'stamp',
key: randomId(),
isDrag: false,
firstXPos: widget.x,
firstYPos: widget.y,
yBottom: 0,
scale: 1,
isMobile: false,
zIndex: 1,
type: widget.type,
widgetValue: '',
options: widget.type === 'signature' ? signOpt : widget.options,
Width: widget.w,
Height: widget.h,
xPosition: widget.x,
yPosition: widget.y,
};
if (page) {
@@ -14,6 +14,7 @@ export default async function draftDocument(request, response) {
const SendinOrder = request.body.sendInOrder || false;
// console.log('fileData ', fileData);
const protocol = customAPIurl();
const baseUrl = new URL(process.env.SERVER_URL);
try {
const reqToken = request.headers['x-api-token'];
@@ -135,7 +136,7 @@ export default async function draftDocument(request, response) {
}
return response.json({
objectId: res.id,
url: protocol + '/load/signmicroapp/placeholdersign/' + res.id,
url: `${baseUrl.origin}/placeholdersign/${res.id}`,
});
} else {
if (request.posthog) {
@@ -0,0 +1,690 @@
/**
*
* @param {Parse} Parse
*/
exports.up = async Parse => {
const className = 'w_menu';
const userMenu = new Parse.Query(className);
const updateUserMenu = await userMenu.get('H9vRfEYKhT');
updateUserMenu.set('menuItems', [
{
icon: 'fas fa-tachometer-alt',
title: 'Dashboard',
target: '',
pageType: 'dashboard',
description: '',
objectId: '35KBoSgoAK',
},
{
icon: 'fas fa-pen-nib',
title: 'Sign yourself',
target: '_self',
pageType: 'form',
description: '',
objectId: 'sHAnZphf69',
},
{
icon: 'fa-solid fa-paper-plane',
title: 'Request signatures',
target: '_self',
pageType: 'form',
description: '',
objectId: '8mZzFxbG1z',
},
{
icon: 'far fa-newspaper',
title: 'Templates',
target: '_self',
pageType: null,
description: null,
objectId: null,
children: [
{
icon: 'fas fa-file-signature',
title: 'Create template',
target: '_self',
pageType: 'form',
description: '',
objectId: 'template',
},
{
icon: 'fa-solid fa-file-contract',
title: 'Manage templates',
target: '_self',
pageType: 'report',
description: '',
objectId: '6TeaPr321t',
},
],
},
{
icon: 'fas fa-folder',
title: 'OpenSign™ Drive',
target: '_self',
pageType: '',
description: '',
objectId: 'opensigndrive',
},
{
icon: 'fas fa-address-card',
title: 'Reports',
target: '_self',
pageType: null,
description: '',
objectId: null,
children: [
{
icon: 'fas fa-signature',
title: 'Need your sign',
target: '_self',
pageType: 'report',
description: '',
objectId: '4Hhwbp482K',
},
{
icon: 'fas fa-tasks',
title: 'In Progress',
target: '_self',
pageType: 'report',
description: '',
objectId: '1MwEuxLEkF',
},
{
icon: 'fas fa-check-circle',
title: 'Completed',
target: '_self',
pageType: 'report',
description: '',
objectId: 'kQUoW4hUXz',
},
{
icon: 'fas fa-edit',
title: 'Drafts',
target: '_self',
pageType: 'report',
description: '',
objectId: 'ByHuevtCFY',
},
{
icon: 'fas fa-times-circle',
title: 'Declined',
target: '_self',
pageType: 'report',
description: '',
objectId: 'UPr2Fm5WY3',
},
{
icon: 'fas fa-hourglass-end',
title: 'Expired',
target: '_self',
pageType: 'report',
description: '',
objectId: 'zNqBHXHsYH',
},
{
icon: 'fa-solid fa-address-book',
title: 'Contactbook',
target: '_self',
pageType: 'report',
description: '',
objectId: '5KhaPr482K',
},
],
},
{
icon: 'fas fa-cog',
title: 'Settings',
target: '_self',
pageType: null,
description: '',
objectId: null,
children: [
{
icon: 'fas fa-pen-fancy',
title: 'My Signature',
target: '_self',
pageType: '',
description: '',
objectId: 'managesign',
},
{
icon: 'fa-solid fa-key',
title: 'API Token',
target: '_self',
pageType: 'generatetoken',
description: '',
objectId: '',
},
{
icon: 'fa-solid fa-globe',
title: 'Webhook',
target: '_self',
pageType: 'webhook',
description: '',
objectId: '',
},
],
},
]);
const AdminMenu = new Parse.Query(className);
const updateAdminMenu = await AdminMenu.get('VPh91h0ZHk');
updateAdminMenu.set('menuItems', [
{
icon: 'fas fa-tachometer-alt',
title: 'Dashboard',
target: '',
pageType: 'dashboard',
description: '',
objectId: '35KBoSgoAK',
},
{
icon: 'fas fa-pen-nib',
title: 'Sign yourself',
target: '_self',
pageType: 'form',
description: '',
objectId: 'sHAnZphf69',
},
{
icon: 'fa-solid fa-paper-plane',
title: 'Request signatures',
target: '_self',
pageType: 'form',
description: '',
objectId: '8mZzFxbG1z',
},
{
icon: 'far fa-newspaper',
title: 'Templates',
target: '_self',
pageType: null,
description: null,
objectId: null,
children: [
{
icon: 'fas fa-file-signature',
title: 'Create template',
target: '_self',
pageType: 'form',
description: '',
objectId: 'template',
},
{
icon: 'fa-solid fa-file-contract',
title: 'Manage templates',
target: '_self',
pageType: 'report',
description: '',
objectId: '6TeaPr321t',
},
],
},
{
icon: 'fas fa-folder',
title: 'OpenSign™ Drive',
target: '_self',
pageType: '',
description: '',
objectId: 'opensigndrive',
},
{
icon: 'fas fa-address-card',
title: 'Reports',
target: '_self',
pageType: null,
description: '',
objectId: null,
children: [
{
icon: 'fas fa-signature',
title: 'Need your sign',
target: '_self',
pageType: 'report',
description: '',
objectId: '4Hhwbp482K',
},
{
icon: 'fas fa-tasks',
title: 'In Progress',
target: '_self',
pageType: 'report',
description: '',
objectId: '1MwEuxLEkF',
},
{
icon: 'fas fa-check-circle',
title: 'Completed',
target: '_self',
pageType: 'report',
description: '',
objectId: 'kQUoW4hUXz',
},
{
icon: 'fas fa-edit',
title: 'Drafts',
target: '_self',
pageType: 'report',
description: '',
objectId: 'ByHuevtCFY',
},
{
icon: 'fas fa-times-circle',
title: 'Declined',
target: '_self',
pageType: 'report',
description: '',
objectId: 'UPr2Fm5WY3',
},
{
icon: 'fas fa-hourglass-end',
title: 'Expired',
target: '_self',
pageType: 'report',
description: '',
objectId: 'zNqBHXHsYH',
},
{
icon: 'fa-solid fa-address-book',
title: 'Contactbook',
target: '_self',
pageType: 'report',
description: '',
objectId: '5KhaPr482K',
},
],
},
{
icon: 'fas fa-cog',
title: 'Settings',
target: '_self',
pageType: null,
description: '',
objectId: null,
children: [
{
icon: 'fas fa-pen-fancy',
title: 'My Signature',
target: '_self',
pageType: '',
description: '',
objectId: 'managesign',
},
{
icon: 'far fa-user',
title: 'Add User',
target: '_self',
pageType: 'form',
description: '',
objectId: 'lM0xRnM3iE',
},
{
icon: 'fa-solid fa-key',
title: 'API Token',
target: '_self',
pageType: 'generatetoken',
description: '',
objectId: '',
},
{
icon: 'fa-solid fa-globe',
title: 'Webhook',
target: '_self',
pageType: 'webhook',
description: '',
objectId: '',
},
],
},
]);
// TODO: Set the schema here
// Example:
// schema.addString('name').addNumber('cash');
const batch = [updateUserMenu, updateAdminMenu];
return Parse.Object.saveAll(batch, { useMasterKey: true });
};
/**
*
* @param {Parse} Parse
*/
exports.down = async Parse => {
// TODO: set className here
const className = 'w_menu';
const userMenu = new Parse.Query(className);
const revertUserMenu = await userMenu.get('H9vRfEYKhT');
revertUserMenu.set('menuItems', [
{
icon: 'fas fa-tachometer-alt',
title: 'Dashboard',
target: '',
pageType: 'dashboard',
description: '',
objectId: '35KBoSgoAK',
},
{
icon: 'far fa-newspaper',
title: 'New Document',
target: '_self',
pageType: null,
description: null,
objectId: null,
children: [
{
icon: 'fas fa-pen-nib',
title: 'Sign yourself',
target: '_self',
pageType: 'form',
description: '',
objectId: 'sHAnZphf69',
},
{
icon: 'fa-solid fa-paper-plane',
title: 'Request signatures',
target: '_self',
pageType: 'form',
description: '',
objectId: '8mZzFxbG1z',
},
{
icon: 'fas fa-file-signature',
title: 'New template',
target: '_self',
pageType: 'form',
description: '',
objectId: 'template',
},
],
},
{
icon: 'fa-solid fa-file-contract',
title: 'Templates',
target: '_self',
pageType: 'report',
description: '',
objectId: '6TeaPr321t',
},
{
icon: 'fas fa-folder',
title: 'OpenSign™ Drive',
target: '_self',
pageType: '',
description: '',
objectId: 'opensigndrive',
},
{
icon: 'fas fa-address-card',
title: 'Reports',
target: '_self',
pageType: null,
description: '',
objectId: null,
children: [
{
icon: 'fas fa-signature',
title: 'Need your sign',
target: '_self',
pageType: 'report',
description: '',
objectId: '4Hhwbp482K',
},
{
icon: 'fas fa-tasks',
title: 'In Progress',
target: '_self',
pageType: 'report',
description: '',
objectId: '1MwEuxLEkF',
},
{
icon: 'fas fa-check-circle',
title: 'Completed',
target: '_self',
pageType: 'report',
description: '',
objectId: 'kQUoW4hUXz',
},
{
icon: 'fas fa-edit',
title: 'Drafts',
target: '_self',
pageType: 'report',
description: '',
objectId: 'ByHuevtCFY',
},
{
icon: 'fas fa-times-circle',
title: 'Declined',
target: '_self',
pageType: 'report',
description: '',
objectId: 'UPr2Fm5WY3',
},
{
icon: 'fas fa-hourglass-end',
title: 'Expired',
target: '_self',
pageType: 'report',
description: '',
objectId: 'zNqBHXHsYH',
},
{
icon: 'fa-solid fa-address-book',
title: 'Contactbook',
target: '_self',
pageType: 'report',
description: '',
objectId: '5KhaPr482K',
},
],
},
{
icon: 'fas fa-cog',
title: 'Settings',
target: '_self',
pageType: null,
description: '',
objectId: null,
children: [
{
icon: 'fas fa-pen-fancy',
title: 'My Signature',
target: '_self',
pageType: '',
description: '',
objectId: 'managesign',
},
{
icon: 'fa-solid fa-key',
title: 'API Token',
target: '_self',
pageType: 'generatetoken',
description: '',
objectId: '',
},
{
icon: 'fa-solid fa-globe',
title: 'Webhook',
target: '_self',
pageType: 'webhook',
description: '',
objectId: '',
},
],
},
]);
const adminMenu = new Parse.Query(className);
const revertAdminMenu = await adminMenu.get('VPh91h0ZHk');
revertAdminMenu.set('menuItems', [
{
icon: 'fas fa-tachometer-alt',
title: 'Dashboard',
target: '',
pageType: 'dashboard',
description: '',
objectId: '35KBoSgoAK',
},
{
icon: 'far fa-newspaper',
title: 'New Document',
target: '_self',
pageType: null,
description: null,
objectId: null,
children: [
{
icon: 'fas fa-pen-nib',
title: 'Sign yourself',
target: '_self',
pageType: 'form',
description: '',
objectId: 'sHAnZphf69',
},
{
icon: 'fa-solid fa-paper-plane',
title: 'Request signatures',
target: '_self',
pageType: 'form',
description: '',
objectId: '8mZzFxbG1z',
},
{
icon: 'fas fa-file-signature',
title: 'New template',
target: '_self',
pageType: 'form',
description: '',
objectId: 'template',
},
],
},
{
icon: 'fa-solid fa-file-contract',
title: 'Templates',
target: '_self',
pageType: 'report',
description: '',
objectId: '6TeaPr321t',
},
{
icon: 'fas fa-folder',
title: 'OpenSign™ Drive',
target: '_self',
pageType: '',
description: '',
objectId: 'opensigndrive',
},
{
icon: 'fas fa-address-card',
title: 'Reports',
target: '_self',
pageType: null,
description: '',
objectId: null,
children: [
{
icon: 'fas fa-signature',
title: 'Need your sign',
target: '_self',
pageType: 'report',
description: '',
objectId: '4Hhwbp482K',
},
{
icon: 'fas fa-tasks',
title: 'In Progress',
target: '_self',
pageType: 'report',
description: '',
objectId: '1MwEuxLEkF',
},
{
icon: 'fas fa-check-circle',
title: 'Completed',
target: '_self',
pageType: 'report',
description: '',
objectId: 'kQUoW4hUXz',
},
{
icon: 'fas fa-edit',
title: 'Drafts',
target: '_self',
pageType: 'report',
description: '',
objectId: 'ByHuevtCFY',
},
{
icon: 'fas fa-times-circle',
title: 'Declined',
target: '_self',
pageType: 'report',
description: '',
objectId: 'UPr2Fm5WY3',
},
{
icon: 'fas fa-hourglass-end',
title: 'Expired',
target: '_self',
pageType: 'report',
description: '',
objectId: 'zNqBHXHsYH',
},
{
icon: 'fa-solid fa-address-book',
title: 'Contactbook',
target: '_self',
pageType: 'report',
description: '',
objectId: '5KhaPr482K',
},
],
},
{
icon: 'fas fa-cog',
title: 'Settings',
target: '_self',
pageType: null,
description: '',
objectId: null,
children: [
{
icon: 'fas fa-pen-fancy',
title: 'My Signature',
target: '_self',
pageType: '',
description: '',
objectId: 'managesign',
},
{
icon: 'far fa-user',
title: 'Add User',
target: '_self',
pageType: 'form',
description: '',
objectId: 'lM0xRnM3iE',
},
{
icon: 'fa-solid fa-key',
title: 'API Token',
target: '_self',
pageType: 'generatetoken',
description: '',
objectId: '',
},
{
icon: 'fa-solid fa-globe',
title: 'Webhook',
target: '_self',
pageType: 'webhook',
description: '',
objectId: '',
},
],
},
]);
const batch = [revertUserMenu, revertAdminMenu];
return Parse.Object.saveAll(batch, { useMasterKey: true });
};
+34 -20
View File
@@ -54,26 +54,39 @@ if (process.env.USE_LOCAL !== 'TRUE') {
let transporterMail;
let mailgunClient;
let mailgunDomain;
let isMailAdapter = false;
if (process.env.SMTP_ENABLE) {
transporterMail = createTransport({
host: process.env.SMTP_HOST,
port: process.env.SMTP_PORT || 465,
secure: process.env.SMTP_SECURE || true,
auth: {
user: process.env.SMTP_USER_EMAIL,
pass: process.env.SMTP_PASS,
},
});
try {
transporterMail = createTransport({
host: process.env.SMTP_HOST,
port: process.env.SMTP_PORT || 465,
secure: process.env.SMTP_SECURE || true,
auth: {
user: process.env.SMTP_USER_EMAIL,
pass: process.env.SMTP_PASS,
},
});
await transporterMail.verify();
isMailAdapter = true;
} catch (err) {
isMailAdapter = false;
console.log('Please provide valid SMTP credentials');
}
} else if (process.env.MAILGUN_API_KEY) {
const mailgun = new Mailgun(formData);
mailgunClient = mailgun.client({
username: 'api',
key: process.env.MAILGUN_API_KEY,
});
mailgunDomain = process.env.MAILGUN_DOMAIN;
try {
const mailgun = new Mailgun(formData);
mailgunClient = mailgun.client({
username: 'api',
key: process.env.MAILGUN_API_KEY,
});
mailgunDomain = process.env.MAILGUN_DOMAIN;
isMailAdapter = true;
} catch (error) {
isMailAdapter = false;
console.log('Please provide valid Mailgun credentials');
}
}
export const config = {
databaseURI:
process.env.DATABASE_URI || process.env.MONGODB_URI || 'mongodb://localhost:27017/dev',
@@ -82,17 +95,18 @@ export const config = {
},
appId: process.env.APP_ID || 'myAppId',
maxLimit: 500,
maxUploadSize: '30mb',
masterKey: process.env.MASTER_KEY, //Add your master key here. Keep it secret!
masterKeyIps: ['0.0.0.0/0', '::/0'], // '::1'
serverURL: process.env.SERVER_URL || 'http://localhost:8080/app', // Don't forget to change to https if needed
verifyUserEmails: process.env.SMTP_ENABLE || process.env.MAILGUN_API_KEY ? true : false,
serverURL: 'http://localhost:8080/app', // Don't forget to change to https if needed
verifyUserEmails: isMailAdapter === true ? true : false,
publicServerURL: process.env.SERVER_URL || 'http://localhost:8080/app',
// Your apps name. This will appear in the subject and body of the emails that are sent.
appName: 'Open Sign',
allowClientClassCreation: false,
allowExpiredAuthDataToken: false,
encodeParseObjectInCloudFunction: true,
...(process.env.SMTP_ENABLE || process.env.MAILGUN_API_KEY
...(isMailAdapter === true
? {
emailAdapter: {
module: 'parse-server-api-mail-adapter',