mirror of
https://github.com/OpenSignLabs/OpenSign.git
synced 2026-08-31 04:09:46 +02:00
@@ -178,6 +178,24 @@
|
||||
"contributions": [
|
||||
"a11y"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Govinda04",
|
||||
"name": "Govinda Kocharekar",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/50038172?v=4",
|
||||
"profile": "https://github.com/Govinda04",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "crediblebilal",
|
||||
"name": "Bilal Ahmad Bhat",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/55330484?v=4",
|
||||
"profile": "https://bilal.cc",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+9
-2
@@ -39,11 +39,18 @@ DO_ACCESS_KEY_ID=
|
||||
DO_SECRET_ACCESS_KEY=
|
||||
# Digital ocean spaces region or AWS s3 region
|
||||
DO_REGION=us-west
|
||||
# Set this to true id you are using local storage instead of s3 compatible storage
|
||||
# USE_LOCAL=TRUE
|
||||
|
||||
# Email mailgun config (The app will not initialize if any of these 3 variables are not set) *********************************************************************************************************************
|
||||
MAILGUN_API_KEY=
|
||||
# Email mailgun or set SMTP_ENABLE true to use SMTP config (The app will not initialize if any of these 3 variables are not set) *********************************************************************************************************************
|
||||
MAILGUN_API_KEY=XXXXX
|
||||
MAILGUN_DOMAIN=mail.yourdomain.com
|
||||
MAILGUN_SENDER=postmaster@mail.yourdomain.com
|
||||
SMTP_ENABLE=
|
||||
SMTP_HOST=
|
||||
SMTP_PORT=
|
||||
SMTP_USER_EMAIL=
|
||||
SMTP_PASS=
|
||||
|
||||
# Base64 encoded PFX or p12 document signing certificate file *********************************************************************************************************************
|
||||
PFX_BASE64=
|
||||
|
||||
+7
-1
@@ -44,10 +44,16 @@ DO_REGION=us-west
|
||||
# local storage
|
||||
USE_LOCAL=TRUE
|
||||
|
||||
# Email mailgun config (The app will not initialize if any of these 3 variables are not set) *********************************************************************************************************************
|
||||
# Email mailgun or set SMTP_ENABLE true to use SMTP config (The app will not initialize if any of these 3 variables are not set) *********************************************************************************************************************
|
||||
MAILGUN_API_KEY=XXXXX
|
||||
MAILGUN_DOMAIN=mail.yourdomain.com
|
||||
MAILGUN_SENDER=postmaster@mail.yourdomain.com
|
||||
SMTP_ENABLE=
|
||||
SMTP_HOST=
|
||||
SMTP_PORT=
|
||||
SMTP_USER_EMAIL=
|
||||
SMTP_PASS=
|
||||
|
||||
|
||||
# Base64 encoded PFX or p12 document signing certificate file *********************************************************************************************************************
|
||||
PFX_BASE64='MIIKCQIBAzCCCc8GCSqGSIb3DQEHAaCCCcAEggm8MIIJuDCCBG8GCSqGSIb3DQEH
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
name: "Bug Report"
|
||||
labels: ["bug","up-for-grabs"]
|
||||
title: "[Bug]: "
|
||||
assignees:
|
||||
- andrew-opensignlabs
|
||||
description: Create a bug report to help us make OpenSign™ the world's best document e-signature platform
|
||||
body:
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Issue Description
|
||||
description: Please provide a clear & concise description of the problem.
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Expected Behavior
|
||||
description: Describe what you expected to happen.
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Current Behavior
|
||||
description: Describe what is happening instead.
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Steps to reproduce
|
||||
description: Please provide step-by-step instructions to reproduce the issue. Include code snippets, URLs, error messages and any other relevant information.
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Screenshots of the issue(optional)
|
||||
description: Add screenshots to better explain the issue.
|
||||
- type: input
|
||||
attributes:
|
||||
label: Operating System [e.g. MacOS Sonoma 14.1, Windows 11]
|
||||
- type: dropdown
|
||||
id: browsers
|
||||
attributes:
|
||||
label: What browsers are you seeing the problem on?
|
||||
multiple: true
|
||||
options:
|
||||
- Chrome
|
||||
- Firefox
|
||||
- Safari
|
||||
- Microsoft Edge
|
||||
default: 0
|
||||
- type: input
|
||||
attributes:
|
||||
label: What version of OpenSign™ are you seeing this issue on? [e.g. 1.0.6]
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: environment
|
||||
attributes:
|
||||
label: What environment are you seeing the problem on?
|
||||
multiple: true
|
||||
options:
|
||||
- Production (app.opensignlabs.com)
|
||||
- Staging (staging-app.opensignlabs.com)
|
||||
- Hosted (app.yourdomain.com)
|
||||
- Dev (localhost or vercel)
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Please check the boxes that apply to this issue report.
|
||||
options:
|
||||
- label: I have searched the existing issues & discussions to make sure that this is not a duplicate.
|
||||
validations:
|
||||
required: true
|
||||
- type: checkboxes
|
||||
id: terms
|
||||
attributes:
|
||||
label: Code of Conduct
|
||||
description: By submitting this issue, you agree to follow our [Code of Conduct](https://www.opensignlabs.com)
|
||||
options:
|
||||
- label: I agree to follow this project's Code of Conduct
|
||||
required: true
|
||||
- label: I have searched the existing issues & discussions to make sure that this is not a duplicate.
|
||||
required: true
|
||||
@@ -0,0 +1,70 @@
|
||||
name: Feature Request
|
||||
description: Suggest an idea for OpenSign™
|
||||
title: "Feature Request: [Short Description]"
|
||||
labels: [feature request, needs triage]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
## Thanks for taking the time to fill out this feature request!
|
||||
|
||||
- type: input
|
||||
id: title
|
||||
attributes:
|
||||
label: Feature Title
|
||||
description: What would you call this feature?
|
||||
placeholder: e.g., Advanced Signature Verification
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: feature-description
|
||||
attributes:
|
||||
label: Feature Description
|
||||
description: |
|
||||
Please provide a detailed description of the feature you're proposing.
|
||||
placeholder: |
|
||||
e.g., I'm proposing an advanced signature verification feature that...
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: featuretype
|
||||
attributes:
|
||||
label: What type of feature are you requesting?
|
||||
multiple: true
|
||||
options:
|
||||
- UI/UX Improvement
|
||||
- Security / Compliance
|
||||
- Performance / Optimization
|
||||
- 3rd party integration
|
||||
- Other
|
||||
- type: dropdown
|
||||
id: importance
|
||||
attributes:
|
||||
label: Importance
|
||||
description: How important is this feature to you?
|
||||
options:
|
||||
- Critical
|
||||
- High
|
||||
- Medium
|
||||
- Low
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: additional-context
|
||||
attributes:
|
||||
label: Additional Context
|
||||
description: Any other context or screenshots about the feature request here.
|
||||
placeholder: Additional details, examples, or screenshots...
|
||||
|
||||
- type: checkboxes
|
||||
id: terms
|
||||
attributes:
|
||||
label: Code of Conduct
|
||||
description: By submitting this issue, you agree to follow our [Code of Conduct](https://www.opensignlabs.com)
|
||||
options:
|
||||
- label: I agree to follow this project's Code of Conduct
|
||||
required: true
|
||||
- label: I have searched the existing issues & discussions to make sure that this is not a duplicate.
|
||||
required: true
|
||||
@@ -128,6 +128,8 @@ We would like to thank all our contributors and users for their support and feed
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/rishabjasrotia"><img src="https://avatars.githubusercontent.com/u/33950743?v=4?s=100" width="100px;" alt="Rishab"/><br /><sub><b>Rishab</b></sub></a><br /><a href="#code-rishabjasrotia" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://session.it"><img src="https://avatars.githubusercontent.com/u/327285?v=4?s=100" width="100px;" alt="Maurizio Pillitu"/><br /><sub><b>Maurizio Pillitu</b></sub></a><br /><a href="#bug-maoo" title="Bug reports">🐛</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://luisparra.dev"><img src="https://avatars.githubusercontent.com/u/16653744?v=4?s=100" width="100px;" alt="Luis Parra"/><br /><sub><b>Luis Parra</b></sub></a><br /><a href="#a11y-lsprr" title="Accessibility">️️️️♿️</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Govinda04"><img src="https://avatars.githubusercontent.com/u/50038172?v=4?s=100" width="100px;" alt="Govinda Kocharekar"/><br /><sub><b>Govinda Kocharekar</b></sub></a><br /><a href="#code-Govinda04" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://bilal.cc"><img src="https://avatars.githubusercontent.com/u/55330484?v=4?s=100" width="100px;" alt="Bilal Ahmad Bhat"/><br /><sub><b>Bilal Ahmad Bhat</b></sub></a><br /><a href="#code-crediblebilal" title="Code">💻</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@@ -42,7 +42,8 @@
|
||||
"scripts": {
|
||||
"start": "serve -s build",
|
||||
"start-dev": "mf-cra start",
|
||||
"build": "rm -rf public/mfbuild && npm run micro && CI=false && mf-cra build",
|
||||
"version": "curl -s https://api.github.com/repos/opensignlabs/opensign/releases/latest | grep '\"tag_name\":' | awk -F '\"' '{print $4}' > ./public/version.txt",
|
||||
"build": "npm run version && rm -rf public/mfbuild && npm run micro && CI=false && mf-cra build",
|
||||
"micro": "cd ../../microfrontends/SignDocuments && npm install && npm run build",
|
||||
"test": "react-scripts test",
|
||||
"eject": "react-scripts eject",
|
||||
@@ -85,4 +86,4 @@
|
||||
"pretty-quick": "^3.1.3",
|
||||
"tailwindcss": "^3.3.3"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
v1.0.5-beta
|
||||
@@ -1,8 +1,20 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import Package from "../../package.json";
|
||||
|
||||
import axios from "axios";
|
||||
const Footer = () => {
|
||||
const [showButton, setShowButton] = useState(false);
|
||||
const [version, setVersion] = useState("");
|
||||
useEffect(() => {
|
||||
axios
|
||||
.get("/version.txt")
|
||||
.then((response) => {
|
||||
setVersion(response.data); // Set the retrieved data to the state variable
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error reading the file:", error);
|
||||
});
|
||||
}, []);
|
||||
|
||||
const handleScroll = () => {
|
||||
if (window.pageYOffset >= 50) {
|
||||
setShowButton(true);
|
||||
@@ -25,16 +37,12 @@ const Footer = () => {
|
||||
}, []);
|
||||
|
||||
const appName = "OpenSign™";
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="bg-[#222c3c] text-[#98a6ba] text-center text-[13px] py-3">
|
||||
All Rights Reserved © {new Date().getFullYear()}
|
||||
{appName}{" "}
|
||||
(version:{" "}
|
||||
{localStorage.getItem("appVersion") &&
|
||||
`${Package.version}.${localStorage.getItem("appVersion")}`}
|
||||
)
|
||||
{appName} ( version: {version ? version : `${Package.version} `})
|
||||
</div>
|
||||
<button
|
||||
className={`${
|
||||
|
||||
@@ -43,8 +43,9 @@ const GoogleSignInBtn = ({
|
||||
});
|
||||
});
|
||||
const clearStorage = async () => {
|
||||
await Parse.User.logOut();
|
||||
|
||||
if (Parse.User.current()) {
|
||||
await Parse.User.logOut();
|
||||
}
|
||||
let baseUrl = localStorage.getItem("BaseUrl12");
|
||||
let appid = localStorage.getItem("AppID12");
|
||||
let applogo = localStorage.getItem("appLogo");
|
||||
@@ -74,7 +75,6 @@ const GoogleSignInBtn = ({
|
||||
localStorage.setItem("userSettings", userSettings);
|
||||
localStorage.setItem("baseUrl", baseUrl);
|
||||
localStorage.setItem("parseAppId", appid);
|
||||
|
||||
};
|
||||
const responseGoogle = async (response) => {
|
||||
clearStorage();
|
||||
|
||||
@@ -9,6 +9,7 @@ function DashboardReport(props) {
|
||||
const [isLoader, setIsLoader] = useState(true);
|
||||
const [reportName, setReportName] = useState("");
|
||||
const [actions, setActions] = useState([]);
|
||||
const [heading, setHeading] = useState([]);
|
||||
const [isNextRecord, setIsNextRecord] = useState(false);
|
||||
const [isMoreDocs, setIsMoreDocs] = useState(true);
|
||||
const abortController = new AbortController();
|
||||
@@ -43,6 +44,7 @@ function DashboardReport(props) {
|
||||
if (json) {
|
||||
setActions(json.actions);
|
||||
setReportName(json.reportName);
|
||||
setHeading(json.heading);
|
||||
Parse.serverURL = localStorage.getItem("BaseUrl12");
|
||||
Parse.initialize(localStorage.getItem("AppID12"));
|
||||
const currentUser = Parse.User.current().id;
|
||||
@@ -140,7 +142,9 @@ function DashboardReport(props) {
|
||||
<ReportTable
|
||||
ReportName={reportName}
|
||||
List={List}
|
||||
setList={setList}
|
||||
actions={actions}
|
||||
heading={heading}
|
||||
setIsNextRecord={setIsNextRecord}
|
||||
isMoreDocs={isMoreDocs}
|
||||
docPerPage={docPerPage}
|
||||
|
||||
@@ -42,9 +42,8 @@ const Sidebar = ({ isOpen, closeSidebar }) => {
|
||||
|
||||
return (
|
||||
<aside
|
||||
className={`${isOpen ? "block" : "hidden"
|
||||
} bg-white text-[#444] h-screen w-full md:w-[300px] overflow-y-auto transform transition-transform z-40 ${isOpen ? "translate-x-0" : "-translate-x-full"
|
||||
}`}
|
||||
className={`bg-white text-[#444] h-screen w-full md:w-[300px] overflow-y-auto transform transition-transform z-40 md:translate-x-0
|
||||
${isOpen ? "translate-x-0 block" : "-translate-x-full hidden"}`}
|
||||
>
|
||||
<div className="flex px-2 py-3 gap-2 items-center shadow-md">
|
||||
<div className="w-[75px] h-[75px] rounded-full ring-[2px] ring-offset-2 ring-gray-400 overflow-hidden">
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
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"];
|
||||
switch (id) {
|
||||
// draft documents report
|
||||
case "ByHuevtCFY":
|
||||
return {
|
||||
reportName: "Draft Documents",
|
||||
heading: head,
|
||||
actions: [
|
||||
{
|
||||
btnLabel: "sign",
|
||||
@@ -21,6 +23,7 @@ export default function reportJson(id) {
|
||||
case "4Hhwbp482K":
|
||||
return {
|
||||
reportName: "Need your sign",
|
||||
heading: head,
|
||||
actions: [
|
||||
{
|
||||
btnLabel: "sign",
|
||||
@@ -36,6 +39,7 @@ export default function reportJson(id) {
|
||||
case "1MwEuxLEkF":
|
||||
return {
|
||||
reportName: "In-progress documents",
|
||||
heading: head,
|
||||
actions: [
|
||||
{
|
||||
btnLabel: "View",
|
||||
@@ -51,6 +55,7 @@ export default function reportJson(id) {
|
||||
case "kQUoW4hUXz":
|
||||
return {
|
||||
reportName: "Completed Documents",
|
||||
heading: head,
|
||||
actions: [
|
||||
{
|
||||
btnLabel: "View",
|
||||
@@ -66,6 +71,7 @@ export default function reportJson(id) {
|
||||
case "UPr2Fm5WY3":
|
||||
return {
|
||||
reportName: "Declined Documents",
|
||||
heading: head,
|
||||
actions: [
|
||||
{
|
||||
btnLabel: "View",
|
||||
@@ -81,6 +87,7 @@ export default function reportJson(id) {
|
||||
case "zNqBHXHsYH":
|
||||
return {
|
||||
reportName: "Expired Documents",
|
||||
heading: head,
|
||||
actions: [
|
||||
{
|
||||
btnLabel: "View",
|
||||
@@ -96,6 +103,7 @@ export default function reportJson(id) {
|
||||
case "d9k3UfYHBc":
|
||||
return {
|
||||
reportName: "Recently sent for signatures",
|
||||
heading: head,
|
||||
actions: [
|
||||
{
|
||||
btnLabel: "View",
|
||||
@@ -111,6 +119,7 @@ export default function reportJson(id) {
|
||||
case "5Go51Q7T8r":
|
||||
return {
|
||||
reportName: "Recent signature requests",
|
||||
heading: head,
|
||||
actions: [
|
||||
{
|
||||
btnLabel: "Sign",
|
||||
@@ -126,6 +135,7 @@ export default function reportJson(id) {
|
||||
case "kC5mfynCi4":
|
||||
return {
|
||||
reportName: "Drafts",
|
||||
heading: head,
|
||||
actions: [
|
||||
{
|
||||
btnLabel: "sign",
|
||||
@@ -137,6 +147,20 @@ export default function reportJson(id) {
|
||||
}
|
||||
]
|
||||
};
|
||||
// contactbook report
|
||||
case "5KhaPr482K":
|
||||
return {
|
||||
reportName: "Contactbook",
|
||||
heading: contactbook,
|
||||
actions: [
|
||||
{
|
||||
btnLabel: "",
|
||||
btnColor: "#f55a42",
|
||||
textColor: "white",
|
||||
btnIcon: "fa-solid fa-trash"
|
||||
}
|
||||
]
|
||||
};
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import { useSelector } from "react-redux";
|
||||
import Parse from "parse";
|
||||
const HomeLayout = ({ children }) => {
|
||||
const { width } = useWindowSize();
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [isOpen, setIsOpen] = useState(true);
|
||||
const arr = useSelector((state) => state.TourSteps);
|
||||
|
||||
// reactour state
|
||||
@@ -19,13 +19,11 @@ const HomeLayout = ({ children }) => {
|
||||
const [tourConfigs, setTourConfigs] = useState([]);
|
||||
|
||||
const showSidebar = () => {
|
||||
setIsOpen(!isOpen);
|
||||
setIsOpen(value => !value);
|
||||
};
|
||||
useEffect(() => {
|
||||
if (width && width <= 768) {
|
||||
setIsOpen(false);
|
||||
} else {
|
||||
setIsOpen(true);
|
||||
}
|
||||
}, [width]);
|
||||
|
||||
|
||||
@@ -1,19 +1,23 @@
|
||||
import React, { useState, useEffect, useMemo } from "react";
|
||||
import pad from "../assets/images/pad.svg";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
import axios from "axios";
|
||||
import "../styles/report.css";
|
||||
const ReportTable = ({
|
||||
ReportName,
|
||||
List,
|
||||
setList,
|
||||
actions,
|
||||
heading,
|
||||
setIsNextRecord,
|
||||
isMoreDocs,
|
||||
docPerPage
|
||||
}) => {
|
||||
const navigate = useNavigate();
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
// const pageNumbers = [];
|
||||
|
||||
const [actLoader, setActLoader] = useState({});
|
||||
const [isAlert, setIsAlert] = useState(false);
|
||||
const [isErr, setIsErr] = useState(false);
|
||||
// For loop is used to calculate page numbers visible below table
|
||||
// Initialize pageNumbers using useMemo to avoid unnecessary re-creation
|
||||
const pageNumbers = useMemo(() => {
|
||||
@@ -57,8 +61,34 @@ const ReportTable = ({
|
||||
localStorage.setItem("rowlevel", JSON.stringify(item));
|
||||
// localStorage.setItem("rowlevelMicro");
|
||||
};
|
||||
const handlebtn = () => {
|
||||
console.log("clicked");
|
||||
const handlebtn = async (item) => {
|
||||
if (ReportName === "Contactbook") {
|
||||
setActLoader({ [item.objectId]: true });
|
||||
try {
|
||||
const url =
|
||||
process.env.REACT_APP_SERVERURL + "/classes/contracts_Contactbook/";
|
||||
const body = { IsDeleted: true };
|
||||
const res = await axios.put(url + item.objectId, body, {
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"X-Parse-Application-Id": localStorage.getItem("AppID12"),
|
||||
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
|
||||
}
|
||||
});
|
||||
// console.log("Res ", res.data);
|
||||
if (res.data && res.data.updatedAt) {
|
||||
setActLoader({});
|
||||
setIsAlert(true);
|
||||
const upldatedList = List.filter((x) => x.objectId !== item.objectId);
|
||||
setList(upldatedList);
|
||||
}
|
||||
} catch (err) {
|
||||
console.log("err", err);
|
||||
setIsAlert(true);
|
||||
setIsErr(true);
|
||||
setActLoader({});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Get current list
|
||||
@@ -73,17 +103,27 @@ const ReportTable = ({
|
||||
|
||||
return (
|
||||
<div className="p-2 overflow-x-scroll w-full bg-white rounded-md">
|
||||
{isAlert && (
|
||||
<div
|
||||
className={`alert alert-${isErr ? "danger" : "success"} alertBox`}
|
||||
role="alert"
|
||||
onAnimationEnd={() => setIsAlert(false)}
|
||||
>
|
||||
{isErr
|
||||
? "Something went wrong, Please try again later!"
|
||||
: "Record deleted successfully!"}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<h2 className="text-[23px] font-light my-2">{ReportName}</h2>
|
||||
<table className="table-auto w-full border-collapse">
|
||||
<thead className="text-[14px]">
|
||||
<tr className="border-y-[1px]">
|
||||
<th className="px-4 py-2 font-thin">Sr.No</th>
|
||||
<th className="px-4 py-2 font-thin">Name</th>
|
||||
<th className="px-4 py-2 font-thin">Note</th>
|
||||
<th className="px-4 py-2 font-thin">Folder</th>
|
||||
<th className="px-4 py-2 font-thin">File</th>
|
||||
<th className="px-4 py-2 font-thin">Owner</th>
|
||||
<th className="px-4 py-2 font-thin">Signers</th>
|
||||
{heading?.map((item, index) => (
|
||||
<React.Fragment key={index}>
|
||||
<th className="px-4 py-2 font-thin">{item}</th>
|
||||
</React.Fragment>
|
||||
))}
|
||||
{actions?.length > 0 && (
|
||||
<th className="px-4 py-2 font-thin">Action</th>
|
||||
)}
|
||||
@@ -92,61 +132,115 @@ const ReportTable = ({
|
||||
<tbody className="text-[12px]">
|
||||
{List?.length > 0 ? (
|
||||
<>
|
||||
{currentLists.map((item, index) => (
|
||||
<tr className="border-y-[1px]" key={index}>
|
||||
<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>
|
||||
<td className="px-4 py-2">
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
title={item?.URL}
|
||||
href={item?.URL}
|
||||
download={item?.URL}
|
||||
className="text-[blue] hover:text-[blue] hover:underline"
|
||||
>
|
||||
{item?.URL ? "Download" : "-"}
|
||||
</a>
|
||||
</td>
|
||||
{currentLists.map((item, index) =>
|
||||
ReportName === "Contactbook" ? (
|
||||
<tr className="border-y-[1px]" key={index}>
|
||||
<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>
|
||||
<td className="px-4 py-2 flex flex-col justify-center items-center gap-2 text-white">
|
||||
{actions?.length > 0 &&
|
||||
actions.map((act, index) => (
|
||||
<button
|
||||
key={index}
|
||||
onClick={() =>
|
||||
act?.redirectUrl
|
||||
? handlemicroapp(item, act.redirectUrl)
|
||||
: handlebtn(item)
|
||||
}
|
||||
className={`flex justify-center items-center gap-1 px-2 py-1 rounded shadow`}
|
||||
style={{
|
||||
backgroundColor: act.btnColor
|
||||
? act.btnColor
|
||||
: "#3ac9d6",
|
||||
color: act?.textColor ? act?.textColor : "white"
|
||||
}}
|
||||
>
|
||||
<span>
|
||||
{act?.btnIcon && (
|
||||
<i
|
||||
className={
|
||||
actLoader[item.objectId]
|
||||
? "fa-solid fa-spinner fa-spin-pulse"
|
||||
: act.btnIcon
|
||||
}
|
||||
></i>
|
||||
)}
|
||||
</span>
|
||||
{act?.btnLabel && (
|
||||
<span className="uppercase">
|
||||
{act?.btnLabel ? act.btnLabel : "View"}
|
||||
</span>
|
||||
)}
|
||||
</button>
|
||||
))}
|
||||
</td>
|
||||
</tr>
|
||||
) : (
|
||||
<tr className="border-y-[1px]" key={index}>
|
||||
<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>
|
||||
<td className="px-4 py-2">
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
title={item?.URL}
|
||||
href={item?.URL}
|
||||
download={item?.URL}
|
||||
className="text-[blue] hover:text-[blue] hover:underline"
|
||||
>
|
||||
{item?.URL ? "Download" : "-"}
|
||||
</a>
|
||||
</td>
|
||||
|
||||
<td className="px-4 py-2">{formatRow(item?.ExtUserPtr)}</td>
|
||||
<td className="px-4 py-2">
|
||||
{item?.Signers ? formatRow(item?.Signers) : "-"}
|
||||
</td>
|
||||
<td className="px-4 py-2 flex flex-col justify-center items-center gap-2 text-white">
|
||||
{actions?.length > 0 &&
|
||||
actions.map((act, index) => (
|
||||
<button
|
||||
key={index}
|
||||
onClick={() =>
|
||||
act?.redirectUrl
|
||||
? handlemicroapp(item, act.redirectUrl)
|
||||
: handlebtn(item)
|
||||
}
|
||||
className={`flex justify-center items-center w-full gap-1 px-2 py-1 rounded shadow`}
|
||||
style={{
|
||||
backgroundColor: act.btnColor
|
||||
? act.btnColor
|
||||
: "#3ac9d6",
|
||||
color: act?.textColor ? act?.textColor : "white"
|
||||
}}
|
||||
>
|
||||
<span>
|
||||
{act?.btnIcon && <i className={act.btnIcon}></i>}
|
||||
</span>
|
||||
<span className="uppercase">
|
||||
{act?.btnLabel ? act.btnLabel : "view"}
|
||||
</span>
|
||||
</button>
|
||||
// )
|
||||
))}
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
<td className="px-4 py-2">{formatRow(item?.ExtUserPtr)}</td>
|
||||
<td className="px-4 py-2">
|
||||
{item?.Signers ? formatRow(item?.Signers) : "-"}
|
||||
</td>
|
||||
<td className="px-4 py-2 flex flex-col justify-center items-center gap-2 text-white">
|
||||
{actions?.length > 0 &&
|
||||
actions.map((act, index) => (
|
||||
<button
|
||||
key={index}
|
||||
onClick={() =>
|
||||
act?.redirectUrl
|
||||
? handlemicroapp(item, act.redirectUrl)
|
||||
: handlebtn(item)
|
||||
}
|
||||
className={`flex justify-center items-center w-full gap-1 px-2 py-1 rounded shadow`}
|
||||
style={{
|
||||
backgroundColor: act.btnColor
|
||||
? act.btnColor
|
||||
: "#3ac9d6",
|
||||
color: act?.textColor ? act?.textColor : "white"
|
||||
}}
|
||||
>
|
||||
<span>
|
||||
{act?.btnIcon && (
|
||||
<i
|
||||
className={
|
||||
actLoader
|
||||
? "fa-solid fa-spinner fa-spin-pulse"
|
||||
: act.btnIcon
|
||||
}
|
||||
></i>
|
||||
)}
|
||||
</span>
|
||||
<span className="uppercase">
|
||||
{act?.btnLabel ? act.btnLabel : "view"}
|
||||
</span>
|
||||
</button>
|
||||
// )
|
||||
))}
|
||||
</td>
|
||||
</tr>
|
||||
)
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<></>
|
||||
|
||||
@@ -2,11 +2,12 @@ import React, { useState, useEffect } from "react";
|
||||
import Parse from "parse";
|
||||
import "../styles/loader.css";
|
||||
import GetDashboard from "../components/dashboard/GetDashboard";
|
||||
import { Navigate, useParams } from "react-router-dom";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
import Title from "../components/Title";
|
||||
import { save_tourSteps } from "../redux/actions";
|
||||
import { connect } from "react-redux";
|
||||
const Dashboard = (props) => {
|
||||
const navigate = useNavigate();
|
||||
const { id } = useParams();
|
||||
const [dashboard, setdashboard] = useState([]);
|
||||
const [classnameArray, setclassnameArray] = useState([]);
|
||||
@@ -15,6 +16,19 @@ const Dashboard = (props) => {
|
||||
const [parseAppId] = useState(localStorage.getItem("parseAppId"));
|
||||
const [defaultQuery, setDefaultQuery] = useState("");
|
||||
|
||||
useEffect(() => {
|
||||
if (localStorage.getItem("accesstoken")) {
|
||||
if (id !== undefined) {
|
||||
getDashboard(id);
|
||||
} else {
|
||||
getDashboard(localStorage.getItem("PageLanding"));
|
||||
}
|
||||
} else {
|
||||
navigate("/", { replace: true });
|
||||
}
|
||||
// eslint-disable-next-line
|
||||
}, [id]);
|
||||
|
||||
const getDashboard = async (id) => {
|
||||
setloading(true);
|
||||
try {
|
||||
@@ -93,20 +107,6 @@ const Dashboard = (props) => {
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (id !== undefined) {
|
||||
getDashboard(id);
|
||||
} else {
|
||||
getDashboard(localStorage.getItem("PageLanding"));
|
||||
}
|
||||
|
||||
// eslint-disable-next-line
|
||||
}, [id]);
|
||||
|
||||
if (localStorage.getItem("accesstoken") === "" || null) {
|
||||
return <Navigate to="/" />;
|
||||
}
|
||||
|
||||
let _dash = (
|
||||
<GetDashboard
|
||||
dashboard={dashboard}
|
||||
|
||||
@@ -12,6 +12,7 @@ const Report = () => {
|
||||
const [isLoader, setIsLoader] = useState(true);
|
||||
const [reportName, setReportName] = useState("");
|
||||
const [actions, setActions] = useState([]);
|
||||
const [heading, setHeading] = useState([]);
|
||||
const [isNextRecord, setIsNextRecord] = useState(false);
|
||||
const [isMoreDocs, setIsMoreDocs] = useState(true);
|
||||
const abortController = new AbortController();
|
||||
@@ -47,6 +48,7 @@ const Report = () => {
|
||||
const json = reportJson(id);
|
||||
if (json) {
|
||||
setActions(json.actions);
|
||||
setHeading(json.heading);
|
||||
setReportName(json.reportName);
|
||||
Parse.serverURL = localStorage.getItem("BaseUrl12");
|
||||
Parse.initialize(localStorage.getItem("AppID12"));
|
||||
@@ -146,7 +148,9 @@ const Report = () => {
|
||||
<ReportTable
|
||||
ReportName={reportName}
|
||||
List={List}
|
||||
setList={setList}
|
||||
actions={actions}
|
||||
heading={heading}
|
||||
setIsNextRecord={setIsNextRecord}
|
||||
isMoreDocs={isMoreDocs}
|
||||
docPerPage={docPerPage}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
.alertBox {
|
||||
z-index: 1;
|
||||
position: absolute;
|
||||
top: 10%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
font-size: 13px;
|
||||
animation: inAnimation 2s ease-in-out;
|
||||
}
|
||||
|
||||
@keyframes inAnimation {
|
||||
0% {
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
25% {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
50% {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
75% {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import reportJson from './reportsJson.js';
|
||||
import axios from 'axios'
|
||||
import axios from 'axios';
|
||||
|
||||
export default async function getReport(request) {
|
||||
const reportId = request.params.reportId;
|
||||
@@ -19,6 +19,7 @@ export default async function getReport(request) {
|
||||
const userId = userRes.data && userRes.data.objectId;
|
||||
if (userId) {
|
||||
const json = reportId && reportJson(reportId, userId);
|
||||
const clsName = reportId === '5KhaPr482K' ? 'contracts_Contactbook' : 'contracts_Document';
|
||||
if (json) {
|
||||
const { params, keys } = json;
|
||||
const orderBy = '-updatedAt';
|
||||
@@ -29,7 +30,7 @@ export default async function getReport(request) {
|
||||
'X-Parse-Application-Id': appId,
|
||||
'X-Parse-Master-Key': process.env.MASTER_KEY,
|
||||
};
|
||||
const url = `${serverUrl}/classes/contracts_Document?where=${strParams}&keys=${strKeys}&order=${orderBy}&skip=${skip}&limit=${limit}&include=AuditTrail.UserPtr`;
|
||||
const url = `${serverUrl}/classes/${clsName}?where=${strParams}&keys=${strKeys}&order=${orderBy}&skip=${skip}&limit=${limit}&include=AuditTrail.UserPtr`;
|
||||
const res = await axios.get(url, { headers: headers });
|
||||
if (res.data && res.data.results) {
|
||||
return res.data.results;
|
||||
|
||||
@@ -198,6 +198,20 @@ export default function reportJson(id, userId) {
|
||||
},
|
||||
keys: ['Name', 'Note', 'Folder.Name', 'URL', 'ExtUserPtr.Name', 'Signers.Name'],
|
||||
};
|
||||
// contact book report
|
||||
case '5KhaPr482K':
|
||||
return {
|
||||
reportName: 'Contactbook',
|
||||
params: {
|
||||
CreatedBy: {
|
||||
__type: 'Pointer',
|
||||
className: '_User',
|
||||
objectId: currentUserId,
|
||||
},
|
||||
IsDeleted: { $ne: true },
|
||||
},
|
||||
keys: ['Name', 'Email', 'Phone'],
|
||||
};
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,556 @@
|
||||
/**
|
||||
*
|
||||
* @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: '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: 'fas fa-file-signature',
|
||||
title: 'Request signatures',
|
||||
target: '_self',
|
||||
pageType: 'form',
|
||||
description: '',
|
||||
objectId: '8mZzFxbG1z',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-folder',
|
||||
title: 'OpenSignDrive™',
|
||||
target: '_self',
|
||||
pageType: 'mf',
|
||||
description: '',
|
||||
objectId:
|
||||
'remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/legadrive',
|
||||
},
|
||||
{
|
||||
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: 'mf',
|
||||
description: '',
|
||||
objectId:
|
||||
'remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/managesign',
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
||||
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: '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: 'fas fa-file-signature',
|
||||
title: 'Request signatures',
|
||||
target: '_self',
|
||||
pageType: 'form',
|
||||
description: '',
|
||||
objectId: '8mZzFxbG1z',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-folder',
|
||||
title: 'OpenSignDrive™',
|
||||
target: '_self',
|
||||
pageType: 'mf',
|
||||
description: '',
|
||||
objectId:
|
||||
'remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/legadrive',
|
||||
},
|
||||
{
|
||||
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: 'mf',
|
||||
description: '',
|
||||
objectId:
|
||||
'remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/managesign',
|
||||
},
|
||||
{
|
||||
icon: 'far fa-user',
|
||||
title: 'Add User',
|
||||
target: '_self',
|
||||
pageType: 'form',
|
||||
description: '',
|
||||
objectId: 'lM0xRnM3iE',
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
// 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: 'fas fa-file-signature',
|
||||
title: 'Request signatures',
|
||||
target: '_self',
|
||||
pageType: 'form',
|
||||
description: '',
|
||||
objectId: '8mZzFxbG1z',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-folder',
|
||||
title: 'OpenSignDrive™',
|
||||
target: '_self',
|
||||
pageType: 'mf',
|
||||
description: '',
|
||||
objectId:
|
||||
'remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/legadrive',
|
||||
},
|
||||
{
|
||||
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: 'fas fa-cog',
|
||||
title: 'Settings',
|
||||
target: '_self',
|
||||
pageType: null,
|
||||
description: '',
|
||||
objectId: null,
|
||||
children: [
|
||||
{
|
||||
icon: 'fas fa-pen-fancy',
|
||||
title: 'My Signature',
|
||||
target: '_self',
|
||||
pageType: 'mf',
|
||||
description: '',
|
||||
objectId:
|
||||
'remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/managesign',
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
||||
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: 'fas fa-file-signature',
|
||||
title: 'Request signatures',
|
||||
target: '_self',
|
||||
pageType: 'form',
|
||||
description: '',
|
||||
objectId: '8mZzFxbG1z',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-folder',
|
||||
title: 'OpenSignDrive™',
|
||||
target: '_self',
|
||||
pageType: 'mf',
|
||||
description: '',
|
||||
objectId:
|
||||
'remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/legadrive',
|
||||
},
|
||||
{
|
||||
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: 'fas fa-cog',
|
||||
title: 'Settings',
|
||||
target: '_self',
|
||||
pageType: null,
|
||||
description: '',
|
||||
objectId: null,
|
||||
children: [
|
||||
{
|
||||
icon: 'fas fa-pen-fancy',
|
||||
title: 'My Signature',
|
||||
target: '_self',
|
||||
pageType: 'mf',
|
||||
description: '',
|
||||
objectId:
|
||||
'remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/managesign',
|
||||
},
|
||||
{
|
||||
icon: 'far fa-user',
|
||||
title: 'Add User',
|
||||
target: '_self',
|
||||
pageType: 'form',
|
||||
description: '',
|
||||
objectId: 'lM0xRnM3iE',
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
// TODO: Set the schema here
|
||||
// Example:
|
||||
// schema.addString('name').addNumber('cash');
|
||||
const batch = [revertUserMenu, revertAdminMenu];
|
||||
return Parse.Object.saveAll(batch, { useMasterKey: true });
|
||||
};
|
||||
@@ -18,6 +18,7 @@ import FSFilesAdapter from 'parse-server-fs-adapter';
|
||||
import AWS from 'aws-sdk';
|
||||
import { app as customRoute } from './cloud/customRoute/customApp.js';
|
||||
import { exec } from 'child_process';
|
||||
import { createTransport } from 'nodemailer';
|
||||
|
||||
const spacesEndpoint = new AWS.Endpoint(process.env.DO_ENDPOINT);
|
||||
// console.log("configuration ", configuration);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
[{
|
||||
[
|
||||
{
|
||||
"_id": "H9vRfEYKhT",
|
||||
"_created_at": {
|
||||
"$date": "2023-09-04T14:04:00.669Z"
|
||||
@@ -105,6 +106,14 @@
|
||||
"pageType": "report",
|
||||
"description": "",
|
||||
"objectId": "zNqBHXHsYH"
|
||||
},
|
||||
{
|
||||
"icon": "fa-solid fa-address-book",
|
||||
"title": "Contactbook",
|
||||
"target": "_self",
|
||||
"pageType": "report",
|
||||
"description": "",
|
||||
"objectId": "5KhaPr482K"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -237,6 +246,14 @@
|
||||
"pageType": "report",
|
||||
"description": "",
|
||||
"objectId": "zNqBHXHsYH"
|
||||
},
|
||||
{
|
||||
"icon": "fa-solid fa-address-book",
|
||||
"title": "Contactbook",
|
||||
"target": "_self",
|
||||
"pageType": "report",
|
||||
"description": "",
|
||||
"objectId": "5KhaPr482K"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -269,4 +286,5 @@
|
||||
],
|
||||
"menuTitle": "Admin Menu",
|
||||
"menuType": "Side Menu"
|
||||
}]
|
||||
}
|
||||
]
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useState, useRef, useEffect } from "react";
|
||||
import { themeColor } from "../utils/ThemeColor/backColor";
|
||||
import { PDFDocument, rgb } from "pdf-lib";
|
||||
import { PDFDocument } from "pdf-lib";
|
||||
import "../css/signature.css";
|
||||
import axios from "axios";
|
||||
import ModalHeader from "react-bootstrap/esm/ModalHeader";
|
||||
@@ -16,7 +16,9 @@ import {
|
||||
contractDocument,
|
||||
getBase64FromIMG,
|
||||
getBase64FromUrl,
|
||||
urlValidator
|
||||
urlValidator,
|
||||
multiSignEmbed,
|
||||
embedDocId
|
||||
} from "../utils/Utils";
|
||||
import Loader from "./component/loader";
|
||||
import HandleError from "./component/HandleError";
|
||||
@@ -319,29 +321,12 @@ function PdfRequestFiles() {
|
||||
if (isDocId) {
|
||||
pdfBase64 = await getBase64FromUrl(url);
|
||||
} else {
|
||||
for (let i = 0; i < allPages; i++) {
|
||||
const font = await pdfDoc.embedFont("Helvetica");
|
||||
|
||||
const fontSize = 10;
|
||||
const textContent =
|
||||
documentId && `OpenSign™ DocumentId: ${documentId}`;
|
||||
|
||||
const pages = pdfDoc.getPages();
|
||||
const page = pages[i];
|
||||
|
||||
page.drawText(textContent, {
|
||||
x: 10,
|
||||
y: page.getHeight() - 10,
|
||||
size: fontSize,
|
||||
font,
|
||||
color: rgb(0.5, 0.5, 0.5)
|
||||
});
|
||||
}
|
||||
//embed document's object id to all pages in pdf document
|
||||
await embedDocId(pdfDoc, documentId, allPages);
|
||||
pdfBase64 = await pdfDoc.saveAsBase64({
|
||||
useObjectStreams: false
|
||||
});
|
||||
}
|
||||
|
||||
for (let i = 0; i < pngUrl.length; i++) {
|
||||
const imgUrlList = pngUrl[i].pos;
|
||||
const pageNo = pngUrl[i].pageNumber;
|
||||
@@ -381,112 +366,15 @@ function PdfRequestFiles() {
|
||||
}
|
||||
//else if signature is more than one then embed all sign with the use of pdf-lib
|
||||
else if (pngUrl.length > 0 && pngUrl[0].pos.length > 0) {
|
||||
for (let i = 0; i < allPages; i++) {
|
||||
const font = await pdfDoc.embedFont("Helvetica");
|
||||
|
||||
const fontSize = 10;
|
||||
const textContent =
|
||||
documentId && `OpenSign™ DocumentId: ${documentId} `;
|
||||
|
||||
const pages = pdfDoc.getPages();
|
||||
const page = pages[i];
|
||||
|
||||
page.drawText(textContent, {
|
||||
x: 10,
|
||||
y: page.getHeight() - 10,
|
||||
size: fontSize,
|
||||
font,
|
||||
color: rgb(0.5, 0.5, 0.5)
|
||||
});
|
||||
}
|
||||
|
||||
for (let i = 0; i < pngUrl.length; i++) {
|
||||
const pageNo = pngUrl[i].pageNumber;
|
||||
|
||||
const imgUrlList = pngUrl[i].pos;
|
||||
const pages = pdfDoc.getPages();
|
||||
const page = pages[pageNo - 1];
|
||||
|
||||
const images = await Promise.all(
|
||||
imgUrlList.map(async (url) => {
|
||||
let signUrl = url.SignUrl;
|
||||
if (url.ImageType === "image/png") {
|
||||
//function for convert signature png base64 url to jpeg base64
|
||||
const newUrl = await convertPNGtoJPEG(signUrl);
|
||||
signUrl = newUrl;
|
||||
}
|
||||
const checkUrl = urlValidator(signUrl);
|
||||
if (checkUrl) {
|
||||
signUrl = signUrl + "?get";
|
||||
}
|
||||
const res = await fetch(signUrl);
|
||||
return res.arrayBuffer();
|
||||
})
|
||||
);
|
||||
images.forEach(async (imgData, id) => {
|
||||
let img = await pdfDoc.embedJpg(imgData);
|
||||
const imgHeight = imgUrlList[id].Height
|
||||
? imgUrlList[id].Height
|
||||
: 60;
|
||||
const imgWidth = imgUrlList[id].Width
|
||||
? imgUrlList[id].Width
|
||||
: 150;
|
||||
const isMobile = window.innerWidth < 767;
|
||||
const newWidth = window.innerWidth;
|
||||
const scale = isMobile ? pdfOriginalWidth / newWidth : 1;
|
||||
const xPos = (pos) => {
|
||||
//checking both condition mobile and desktop view
|
||||
if (isMobile) {
|
||||
//if pos.isMobile false -- placeholder saved from desktop view then handle position in mobile view divided by scale
|
||||
if (pos.isMobile) {
|
||||
const x = pos.xPosition * (pos.scale / scale);
|
||||
return x * scale + 50;
|
||||
} else {
|
||||
const x = pos.xPosition / scale;
|
||||
return x * scale;
|
||||
}
|
||||
} else {
|
||||
//else if pos.isMobile true -- placeholder saved from mobile or tablet view then handle position in desktop view divide by scale
|
||||
if (pos.isMobile) {
|
||||
const x = pos.xPosition * pos.scale + 50;
|
||||
return x;
|
||||
} else {
|
||||
return pos.xPosition;
|
||||
}
|
||||
}
|
||||
};
|
||||
const yPos = (pos) => {
|
||||
//checking both condition mobile and desktop view
|
||||
const y = pos.yPosition / scale;
|
||||
if (isMobile) {
|
||||
//if pos.isMobile false -- placeholder saved from desktop view then handle position in mobile view divided by scale
|
||||
if (pos.isMobile) {
|
||||
const y = pos.yPosition * (pos.scale / scale);
|
||||
return page.getHeight() - y * scale - imgHeight;
|
||||
} else {
|
||||
return page.getHeight() - y * scale - imgHeight;
|
||||
}
|
||||
} else {
|
||||
//else if pos.isMobile true -- placeholder saved from mobile or tablet view then handle position in desktop view divide by scale
|
||||
if (pos.isMobile) {
|
||||
const y = pos.yPosition * pos.scale;
|
||||
return page.getHeight() - y - imgHeight;
|
||||
} else {
|
||||
return page.getHeight() - pos.yPosition - imgHeight;
|
||||
}
|
||||
}
|
||||
};
|
||||
page.drawImage(img, {
|
||||
x: xPos(imgUrlList[id]),
|
||||
y: yPos(imgUrlList[id]),
|
||||
width: imgWidth,
|
||||
height: imgHeight
|
||||
});
|
||||
});
|
||||
}
|
||||
const pdfBytes = await pdfDoc.saveAsBase64({
|
||||
useObjectStreams: false
|
||||
});
|
||||
//embed document's object id to all pages in pdf document
|
||||
await embedDocId(pdfDoc, documentId, allPages);
|
||||
//embed multi signature in pdf
|
||||
const pdfBytes = await multiSignEmbed(
|
||||
pngUrl,
|
||||
pdfDoc,
|
||||
pdfOriginalWidth,
|
||||
false
|
||||
);
|
||||
|
||||
signPdfFun(pdfBytes, documentId, pngUrl);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useState, useRef, useEffect } from "react";
|
||||
import { PDFDocument, rgb } from "pdf-lib";
|
||||
import { PDFDocument } from "pdf-lib";
|
||||
import "../css/./signature.css";
|
||||
import sign from "../assests/sign3.png";
|
||||
import stamp from "../assests/stamp2.png";
|
||||
@@ -18,7 +18,9 @@ import ModalHeader from "react-bootstrap/esm/ModalHeader";
|
||||
import {
|
||||
convertPNGtoJPEG,
|
||||
contractDocument,
|
||||
getBase64FromIMG
|
||||
getBase64FromIMG,
|
||||
embedDocId,
|
||||
multiSignEmbed
|
||||
} from "../utils/Utils";
|
||||
import { useParams } from "react-router-dom";
|
||||
import Tour from "reactour";
|
||||
@@ -30,7 +32,7 @@ import Header from "./component/header";
|
||||
import RenderPdf from "./component/renderPdf";
|
||||
import { contractUsers, contactBook, urlValidator } from "../utils/Utils";
|
||||
import { modalAlign } from "../utils/Utils";
|
||||
import { $ } from "select-dom";
|
||||
|
||||
//For signYourself inProgress section signer can add sign and complete doc sign.
|
||||
function SignYourSelf() {
|
||||
const [pdfDetails, setPdfDetails] = useState([]);
|
||||
@@ -422,24 +424,7 @@ function SignYourSelf() {
|
||||
//checking if signature is only one then send image url in jpeg formate to server
|
||||
if (xyPostion.length === 1 && xyPostion[0].pos.length === 1) {
|
||||
//embed document's object id to all pages in pdf document
|
||||
for (let i = 0; i < allPages; i++) {
|
||||
const font = await pdfDoc.embedFont("Helvetica");
|
||||
|
||||
const fontSize = 10;
|
||||
const textContent =
|
||||
documentId && `OpenSign™ DocumentId: ${documentId}`;
|
||||
|
||||
const pages = pdfDoc.getPages();
|
||||
const page = pages[i];
|
||||
|
||||
page.drawText(textContent, {
|
||||
x: 10,
|
||||
y: page.getHeight() - 10,
|
||||
size: fontSize,
|
||||
font,
|
||||
color: rgb(0.5, 0.5, 0.5)
|
||||
});
|
||||
}
|
||||
await embedDocId(pdfDoc, documentId, allPages);
|
||||
const pdfBase64 = await pdfDoc.saveAsBase64({
|
||||
useObjectStreams: false
|
||||
});
|
||||
@@ -475,85 +460,15 @@ function SignYourSelf() {
|
||||
}
|
||||
//else if signature is more than one then embed all sign with the use of pdf-lib
|
||||
else if (xyPostion.length > 0 && xyPostion[0].pos.length > 0) {
|
||||
for (let i = 0; i < allPages; i++) {
|
||||
const font = await pdfDoc.embedFont("Helvetica");
|
||||
|
||||
const fontSize = 10;
|
||||
const textContent =
|
||||
documentId && `OpenSign™ DocumentId: ${documentId} `;
|
||||
|
||||
const pages = pdfDoc.getPages();
|
||||
const page = pages[i];
|
||||
|
||||
page.drawText(textContent, {
|
||||
x: 10,
|
||||
y: page.getHeight() - 10,
|
||||
size: fontSize,
|
||||
font,
|
||||
color: rgb(0.5, 0.5, 0.5)
|
||||
});
|
||||
}
|
||||
for (let i = 0; i < pngUrl.length; i++) {
|
||||
const pageNo = pngUrl[i].pageNumber;
|
||||
|
||||
const imgUrlList = pngUrl[i].pos;
|
||||
const pages = pdfDoc.getPages();
|
||||
const page = pages[pageNo - 1];
|
||||
|
||||
const images = await Promise.all(
|
||||
imgUrlList.map(async (url) => {
|
||||
let signUrl = url.SignUrl;
|
||||
|
||||
if (url.ImageType === "image/png") {
|
||||
//function for convert signature png base64 url to jpeg base64
|
||||
const newUrl = await convertPNGtoJPEG(signUrl);
|
||||
signUrl = newUrl;
|
||||
}
|
||||
const checkUrl = urlValidator(signUrl);
|
||||
if (checkUrl) {
|
||||
signUrl = signUrl + "?get";
|
||||
}
|
||||
const res = await fetch(signUrl);
|
||||
|
||||
return res.arrayBuffer();
|
||||
})
|
||||
);
|
||||
images.forEach(async (imgData, id) => {
|
||||
let img = await pdfDoc.embedJpg(imgData);
|
||||
const imgHeight = imgUrlList[id].Height
|
||||
? imgUrlList[id].Height
|
||||
: 60;
|
||||
const imgWidth = imgUrlList[id].Width ? imgUrlList[id].Width : 150;
|
||||
const isMobile = window.innerWidth < 767;
|
||||
const newWidth = window.innerWidth;
|
||||
const scale = isMobile ? pdfOriginalWidth / newWidth : 1;
|
||||
|
||||
const posY = () => {
|
||||
if (isMobile) {
|
||||
if (id === 0) {
|
||||
return (
|
||||
page.getHeight() -
|
||||
imgUrlList[id].yPosition * scale -
|
||||
imgHeight
|
||||
);
|
||||
} else if (id > 0) {
|
||||
return page.getHeight() - imgUrlList[id].yPosition * scale;
|
||||
}
|
||||
} else {
|
||||
return page.getHeight() - imgUrlList[id].yPosition - imgHeight;
|
||||
}
|
||||
};
|
||||
page.drawImage(img, {
|
||||
x: isMobile
|
||||
? imgUrlList[id].xPosition * scale + imgWidth / 2
|
||||
: imgUrlList[id].xPosition,
|
||||
y: posY(),
|
||||
width: imgWidth,
|
||||
height: imgHeight
|
||||
});
|
||||
});
|
||||
}
|
||||
const pdfBytes = await pdfDoc.saveAsBase64({ useObjectStreams: false });
|
||||
//embed document's object id to all pages in pdf document
|
||||
await embedDocId(pdfDoc, documentId, allPages);
|
||||
//embed multi signature in pdf
|
||||
const pdfBytes = await multiSignEmbed(
|
||||
pngUrl,
|
||||
pdfDoc,
|
||||
pdfOriginalWidth,
|
||||
true
|
||||
);
|
||||
signPdfFun(pdfBytes, documentId);
|
||||
}
|
||||
setIsSignPad(false);
|
||||
@@ -574,16 +489,16 @@ function SignYourSelf() {
|
||||
let singleSign;
|
||||
|
||||
const isMobile = window.innerWidth < 767;
|
||||
const newWidth = window.innerWidth;
|
||||
const newWidth = window.innerWidth - 32;
|
||||
const scale = isMobile ? pdfOriginalWidth / newWidth : 1;
|
||||
const imgWidth = xyPosData ? xyPosData.Width : 150;
|
||||
if (xyPostion.length === 1 && xyPostion[0].pos.length === 1) {
|
||||
const height = xyPosData.Height ? xyPosData.Height : 60;
|
||||
const bottomY = xyPosData.isDrag
|
||||
? xyPosData.yBottom * scale - height
|
||||
? xyPosData.yBottom * scale - height * scale
|
||||
: xyPosData.firstYPos
|
||||
? xyPosData.yBottom * scale - height + xyPosData.firstYPos
|
||||
: xyPosData.yBottom * scale - height;
|
||||
? xyPosData.yBottom * scale - height * scale + xyPosData.firstYPos
|
||||
: xyPosData.yBottom * scale - height * scale;
|
||||
|
||||
singleSign = {
|
||||
pdfFile: pdfBase64Url,
|
||||
@@ -591,11 +506,11 @@ function SignYourSelf() {
|
||||
sign: {
|
||||
Base64: base64Url,
|
||||
Left: isMobile
|
||||
? xyPosData.xPosition * scale + imgWidth / 2
|
||||
? xyPosData.xPosition * scale + 43
|
||||
: xyPosData.xPosition,
|
||||
Bottom: bottomY,
|
||||
Width: xyPosData.Width ? xyPosData.Width : 150,
|
||||
Height: height,
|
||||
Width: xyPosData.Width ? xyPosData.Width * scale : 150 * scale,
|
||||
Height: height * scale,
|
||||
Page: pageNo
|
||||
}
|
||||
};
|
||||
|
||||
@@ -274,8 +274,7 @@ function EmailComponent({
|
||||
<span
|
||||
style={{
|
||||
color: "white",
|
||||
fontSize: "13px",
|
||||
marginTop: "2px"
|
||||
fontSize: "13px"
|
||||
}}
|
||||
>
|
||||
{data}
|
||||
@@ -287,7 +286,8 @@ function EmailComponent({
|
||||
src={close}
|
||||
width={10}
|
||||
height={10}
|
||||
style={{ fontWeight: "600", margin: "0 0 10px 2px" }}
|
||||
style={{ fontWeight: "600", marginLeft: "7px" }}
|
||||
className="emailChipClose"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
import React, { useState, useRef, useEffect } from "react";
|
||||
import { PDFDocument, rgb } from "pdf-lib";
|
||||
import { PDFDocument } from "pdf-lib";
|
||||
import "../css/./signature.css";
|
||||
import axios from "axios";
|
||||
import Modal from "react-bootstrap/Modal";
|
||||
@@ -19,7 +19,9 @@ import {
|
||||
contractUsers,
|
||||
contactBook,
|
||||
contractDocument,
|
||||
urlValidator
|
||||
urlValidator,
|
||||
multiSignEmbed,
|
||||
embedDocId
|
||||
} from "../utils/Utils";
|
||||
import Tour from "reactour";
|
||||
import Signedby from "./component/signedby";
|
||||
@@ -424,23 +426,8 @@ function EmbedPdfImage() {
|
||||
if (isDocId) {
|
||||
pdfBase64 = await getBase64FromUrl(url);
|
||||
} else {
|
||||
for (let i = 0; i < allPages; i++) {
|
||||
const font = await pdfDoc.embedFont("Helvetica");
|
||||
|
||||
const fontSize = 10;
|
||||
const textContent = docId && `OpenSign™ DocumentId: ${docId} `;
|
||||
|
||||
const pages = pdfDoc.getPages();
|
||||
const page = pages[i];
|
||||
|
||||
page.drawText(textContent, {
|
||||
x: 10,
|
||||
y: page.getHeight() - 10,
|
||||
size: fontSize,
|
||||
font,
|
||||
color: rgb(0.5, 0.5, 0.5)
|
||||
});
|
||||
}
|
||||
//embed document's object id to all pages in pdf document
|
||||
await embedDocId(pdfDoc, docId, allPages);
|
||||
pdfBase64 = await pdfDoc.saveAsBase64({ useObjectStreams: false });
|
||||
}
|
||||
for (let i = 0; i < xyPostion.length; i++) {
|
||||
@@ -475,115 +462,18 @@ function EmbedPdfImage() {
|
||||
}
|
||||
//else if signature is more than one then embed all sign with the use of pdf-lib
|
||||
else if (xyPostion.length > 0 && xyPostion[0].pos.length > 0) {
|
||||
for (let i = 0; i < allPages; i++) {
|
||||
const font = await pdfDoc.embedFont("Helvetica");
|
||||
|
||||
const fontSize = 10;
|
||||
const textContent = docId && `OpenSign™ DocumentId: ${docId} `;
|
||||
|
||||
const pages = pdfDoc.getPages();
|
||||
const page = pages[i];
|
||||
|
||||
page.drawText(textContent, {
|
||||
x: 10,
|
||||
y: page.getHeight() - 10,
|
||||
size: fontSize,
|
||||
font,
|
||||
color: rgb(0.5, 0.5, 0.5)
|
||||
});
|
||||
}
|
||||
for (let i = 0; i < pngUrl.length; i++) {
|
||||
const pageNo = pngUrl[i].pageNumber;
|
||||
|
||||
const imgUrlList = pngUrl[i].pos;
|
||||
const pages = pdfDoc.getPages();
|
||||
const page = pages[pageNo - 1];
|
||||
|
||||
const images = await Promise.all(
|
||||
imgUrlList.map(async (url) => {
|
||||
let signUrl = url.SignUrl;
|
||||
if (url.ImageType === "image/png") {
|
||||
//function for convert signature png base64 url to jpeg base64
|
||||
const newUrl = await convertPNGtoJPEG(signUrl);
|
||||
signUrl = newUrl;
|
||||
}
|
||||
const checkUrl = urlValidator(signUrl);
|
||||
if (checkUrl) {
|
||||
signUrl = signUrl + "?get";
|
||||
}
|
||||
const res = await fetch(signUrl);
|
||||
|
||||
return res.arrayBuffer();
|
||||
})
|
||||
);
|
||||
images.forEach(async (imgData, id) => {
|
||||
let img = await pdfDoc.embedJpg(imgData);
|
||||
|
||||
const imgHeight = imgUrlList[id].Height
|
||||
? imgUrlList[id].Height
|
||||
: 60;
|
||||
const imgWidth = imgUrlList[id].Width ? imgUrlList[id].Width : 150;
|
||||
const isMobile = window.innerWidth < 767;
|
||||
const newWidth = window.innerWidth;
|
||||
const scale = isMobile ? pdfOriginalWidth / newWidth : 1;
|
||||
const xPos = (pos) => {
|
||||
//checking both condition mobile and desktop view
|
||||
if (isMobile) {
|
||||
//if pos.isMobile false -- placeholder saved from desktop view then handle position in mobile view divided by scale
|
||||
if (pos.isMobile) {
|
||||
const x = pos.xPosition * (pos.scale / scale);
|
||||
return x * scale + 50;
|
||||
} else {
|
||||
const x = pos.xPosition / scale;
|
||||
return x * scale;
|
||||
}
|
||||
} else {
|
||||
//else if pos.isMobile true -- placeholder saved from mobile or tablet view then handle position in desktop view divide by scale
|
||||
if (pos.isMobile) {
|
||||
const x = pos.xPosition * pos.scale + 50;
|
||||
return x;
|
||||
} else {
|
||||
return pos.xPosition;
|
||||
}
|
||||
}
|
||||
};
|
||||
const yPos = (pos) => {
|
||||
//checking both condition mobile and desktop view
|
||||
|
||||
if (isMobile) {
|
||||
//if pos.isMobile false -- placeholder saved from desktop view then handle position in mobile view divided by scale
|
||||
if (pos.isMobile) {
|
||||
const y = pos.yPosition * (pos.scale / scale);
|
||||
return page.getHeight() - y * scale - imgHeight;
|
||||
} else {
|
||||
const y = pos.yPosition / scale;
|
||||
return page.getHeight() - y * scale - imgHeight;
|
||||
}
|
||||
} else {
|
||||
//else if pos.isMobile true -- placeholder saved from mobile or tablet view then handle position in desktop view divide by scale
|
||||
if (pos.isMobile) {
|
||||
const y = pos.yPosition * pos.scale;
|
||||
return page.getHeight() - y - imgHeight;
|
||||
} else {
|
||||
return page.getHeight() - pos.yPosition - imgHeight;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
page.drawImage(img, {
|
||||
x: xPos(imgUrlList[id]),
|
||||
y: yPos(imgUrlList[id]),
|
||||
width: imgWidth,
|
||||
height: imgHeight
|
||||
});
|
||||
});
|
||||
}
|
||||
const pdfBytes = await pdfDoc.saveAsBase64({ useObjectStreams: false });
|
||||
//embed document's object id to all pages in pdf document
|
||||
await embedDocId(pdfDoc, docId, allPages);
|
||||
//embed multi signature in pdf
|
||||
const pdfBytes = await multiSignEmbed(
|
||||
pngUrl,
|
||||
pdfDoc,
|
||||
pdfOriginalWidth,
|
||||
false
|
||||
);
|
||||
signPdfFun(pdfBytes, docId);
|
||||
}
|
||||
|
||||
setIsSignPad(false);
|
||||
|
||||
setXyPostion([]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,6 +80,10 @@
|
||||
padding: 5px 10px;
|
||||
}
|
||||
|
||||
.emailChipClose:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.addEmailInput {
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
@@ -639,6 +643,7 @@ option {
|
||||
|
||||
.stickyfooter {
|
||||
position: fixed;
|
||||
z-index: 32 !important;
|
||||
bottom: 0px;
|
||||
right: 0rem;
|
||||
}
|
||||
@@ -785,4 +790,4 @@ option {
|
||||
|
||||
.signature-backdrop.fade.in {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import axios from "axios";
|
||||
import { $ } from 'select-dom';
|
||||
|
||||
import { $ } from "select-dom";
|
||||
import { rgb } from "pdf-lib";
|
||||
export async function getBase64FromUrl(url) {
|
||||
const data = await fetch(url);
|
||||
const blob = await data.blob();
|
||||
@@ -327,18 +327,155 @@ export const contactBook = async (objectId) => {
|
||||
export function urlValidator(url) {
|
||||
try {
|
||||
const newUrl = new URL(url);
|
||||
return newUrl.protocol === 'http:' || newUrl.protocol === 'https:';
|
||||
return newUrl.protocol === "http:" || newUrl.protocol === "https:";
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
export function modalAlign() {
|
||||
let modalDialog = $('.modal-dialog').getBoundingClientRect();
|
||||
let mobileHead = $('.mobileHead').getBoundingClientRect()
|
||||
let modal = $('.modal-dialog');
|
||||
let modalDialog = $(".modal-dialog").getBoundingClientRect();
|
||||
let mobileHead = $(".mobileHead").getBoundingClientRect();
|
||||
let modal = $(".modal-dialog");
|
||||
if (modalDialog.left < mobileHead.left) {
|
||||
let leftOffset = mobileHead.left - modalDialog.left;
|
||||
modal.style.left = leftOffset + 'px';
|
||||
modal.style.top = (window.innerHeight/3) + 'px';
|
||||
modal.style.left = leftOffset + "px";
|
||||
modal.style.top = window.innerHeight / 3 + "px";
|
||||
}
|
||||
}
|
||||
|
||||
//function for embed multiple signature using pdf-lib
|
||||
export const multiSignEmbed = async (
|
||||
pngUrl,
|
||||
pdfDoc,
|
||||
pdfOriginalWidth,
|
||||
signyourself
|
||||
) => {
|
||||
for (let i = 0; i < pngUrl.length; i++) {
|
||||
const pageNo = pngUrl[i].pageNumber;
|
||||
const imgUrlList = pngUrl[i].pos;
|
||||
const pages = pdfDoc.getPages();
|
||||
const page = pages[pageNo - 1];
|
||||
const images = await Promise.all(
|
||||
imgUrlList.map(async (url) => {
|
||||
let signUrl = url.SignUrl;
|
||||
if (url.ImageType === "image/png") {
|
||||
//function for convert signature png base64 url to jpeg base64
|
||||
const newUrl = await convertPNGtoJPEG(signUrl);
|
||||
signUrl = newUrl;
|
||||
}
|
||||
const checkUrl = urlValidator(signUrl);
|
||||
if (checkUrl) {
|
||||
signUrl = signUrl + "?get";
|
||||
}
|
||||
const res = await fetch(signUrl);
|
||||
return res.arrayBuffer();
|
||||
})
|
||||
);
|
||||
images.forEach(async (imgData, id) => {
|
||||
let img;
|
||||
if (
|
||||
(imgUrlList[id].ImageType &&
|
||||
imgUrlList[id].ImageType === "image/png") ||
|
||||
imgUrlList[id].ImageType === "image/jpeg"
|
||||
) {
|
||||
img = await pdfDoc.embedJpg(imgData);
|
||||
} else {
|
||||
img = await pdfDoc.embedPng(imgData);
|
||||
}
|
||||
const imgHeight = imgUrlList[id].Height ? imgUrlList[id].Height : 60;
|
||||
const imgWidth = imgUrlList[id].Width ? imgUrlList[id].Width : 150;
|
||||
const isMobile = window.innerWidth < 767;
|
||||
const newWidth = window.innerWidth - 32;
|
||||
const scale = isMobile ? pdfOriginalWidth / newWidth : 1;
|
||||
const xPos = (pos) => {
|
||||
if (signyourself) {
|
||||
if (isMobile) {
|
||||
return imgUrlList[id].xPosition * scale + 43;
|
||||
} else {
|
||||
return imgUrlList[id].xPosition;
|
||||
}
|
||||
} else {
|
||||
//checking both condition mobile and desktop view
|
||||
if (isMobile) {
|
||||
//if pos.isMobile false -- placeholder saved from desktop view then handle position in mobile view divided by scale
|
||||
if (pos.isMobile) {
|
||||
const x = pos.xPosition * (pos.scale / scale);
|
||||
return x * scale + 50;
|
||||
} else {
|
||||
const x = pos.xPosition / scale;
|
||||
return x * scale;
|
||||
}
|
||||
} else {
|
||||
//else if pos.isMobile true -- placeholder saved from mobile or tablet view then handle position in desktop view divide by scale
|
||||
if (pos.isMobile) {
|
||||
const x = pos.xPosition * pos.scale + 50;
|
||||
return x;
|
||||
} else {
|
||||
return pos.xPosition;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const yPos = (pos) => {
|
||||
if (signyourself) {
|
||||
if (isMobile) {
|
||||
return (
|
||||
page.getHeight() -
|
||||
imgUrlList[id].yPosition * scale -
|
||||
imgHeight * scale
|
||||
);
|
||||
} else {
|
||||
return page.getHeight() - imgUrlList[id].yPosition - imgHeight;
|
||||
}
|
||||
} else {
|
||||
//checking both condition mobile and desktop view
|
||||
const y = pos.yPosition / scale;
|
||||
if (isMobile) {
|
||||
//if pos.isMobile false -- placeholder saved from desktop view then handle position in mobile view divided by scale
|
||||
if (pos.isMobile) {
|
||||
const y = pos.yPosition * (pos.scale / scale);
|
||||
return page.getHeight() - y * scale - imgHeight;
|
||||
} else {
|
||||
return page.getHeight() - y * scale - imgHeight;
|
||||
}
|
||||
} else {
|
||||
//else if pos.isMobile true -- placeholder saved from mobile or tablet view then handle position in desktop view divide by scale
|
||||
if (pos.isMobile) {
|
||||
const y = pos.yPosition * pos.scale;
|
||||
return page.getHeight() - y - imgHeight;
|
||||
} else {
|
||||
return page.getHeight() - pos.yPosition - imgHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
page.drawImage(img, {
|
||||
x: xPos(imgUrlList[id]),
|
||||
y: yPos(imgUrlList[id]),
|
||||
width: signyourself ? imgWidth * scale : imgWidth,
|
||||
height: signyourself ? imgHeight * scale : imgHeight
|
||||
});
|
||||
});
|
||||
}
|
||||
const pdfBytes = await pdfDoc.saveAsBase64({ useObjectStreams: false });
|
||||
return pdfBytes;
|
||||
};
|
||||
//function for embed document id
|
||||
export const embedDocId = async (pdfDoc, documentId, allPages) => {
|
||||
for (let i = 0; i < allPages; i++) {
|
||||
const font = await pdfDoc.embedFont("Helvetica");
|
||||
const fontSize = 10;
|
||||
const textContent = documentId && `OpenSign™ DocumentId: ${documentId} `;
|
||||
const pages = pdfDoc.getPages();
|
||||
const page = pages[i];
|
||||
page.drawText(textContent, {
|
||||
x: 10,
|
||||
y: page.getHeight() - 10,
|
||||
size: fontSize,
|
||||
font,
|
||||
color: rgb(0.5, 0.5, 0.5)
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user