mirror of
https://github.com/OpenSignLabs/OpenSign.git
synced 2026-08-17 21:25:54 +02:00
Merge branch 'OpenSignLabs:main' into main
This commit is contained in:
@@ -5,8 +5,10 @@
|
||||
The free open source alternative to DocuSign | PandaDoc | SignNow | Adobe Sign | Smartwaiver | SignRequest | HelloSign | Zoho sign.
|
||||
|
||||
[](http://isitmaintained.com/project/opensignlabs/opensign "Average time to resolve an issue")
|
||||
|
||||
[](#contributors)
|
||||

|
||||

|
||||
|
||||
|
||||
<a href="https://www.opensignlabs.com/">Website</a>
|
||||
<span> • </span>
|
||||
@@ -23,12 +25,6 @@ The free open source alternative to DocuSign | PandaDoc | SignNow | Adobe Sign |
|
||||
|
||||
## An Open-Source Alternative to DocuSign, PandaDoc, SignNow, Adobe Sign, Smartwaiver, SignRequest, and HelloSign
|
||||
|
||||
Support us -
|
||||
|
||||
<a href="https://www.producthunt.com/posts/opensign-transforming-how-we-sign-docs?utm_source=badge-featured&utm_medium=badge&utm_souce=badge-opensign-transforming-how-we-sign-docs" target="_blank"><img src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=418556&theme=light" alt="OpenSign™: Transforming How We Sign Docs - Enterprise-Level Document Signing Goes Open-Source | Product Hunt" style="width: 250px; height: 54px;" width="250" height="54" /></a>
|
||||
|
||||
[](https://twitter.com/opensignlabs)
|
||||
|
||||
---
|
||||
</div>
|
||||
|
||||
@@ -88,7 +84,7 @@ We welcome contributions from the open-source community. For more information on
|
||||
|
||||
### License
|
||||
|
||||
OpenSign is licensed under the AGPL License. For more details, see the [LICENSE](LICENSE.md) file.
|
||||
OpenSign is licensed under the AGPL License. For more details, see the [LICENSE](LICENSE) file.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -156,7 +156,35 @@ const DashboardCard = (props) => {
|
||||
if (props.Data.key !== "count") {
|
||||
setresponse(res.data.results[0][props.Data.key]);
|
||||
} else {
|
||||
setresponse(res.data[props.Data.key]);
|
||||
if (props.Label === "Need your Signature") {
|
||||
const listData = res.data?.results.filter(
|
||||
(x) => x.Signers.length > 0
|
||||
);
|
||||
let arr = [];
|
||||
for (const obj of listData) {
|
||||
const isSigner = obj.Signers.some(
|
||||
(item) => item.UserId.objectId === currentUser.id
|
||||
);
|
||||
if (isSigner) {
|
||||
let isRecord;
|
||||
if (obj?.AuditTrail && obj?.AuditTrail.length > 0) {
|
||||
isRecord = obj?.AuditTrail.some(
|
||||
(item) =>
|
||||
item?.UserPtr?.UserId?.objectId === currentUser.id &&
|
||||
item.Activity === "Signed"
|
||||
);
|
||||
} else {
|
||||
isRecord = false;
|
||||
}
|
||||
if (isRecord === false) {
|
||||
arr.push(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
setresponse(arr.length);
|
||||
} else {
|
||||
setresponse(res.data[props.Data.key]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
setresponse(0);
|
||||
|
||||
@@ -34,10 +34,39 @@ function DashboardReport(props) {
|
||||
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
|
||||
};
|
||||
try {
|
||||
const url = `${serverURL}?where=${strParams}&keys=${strKeys}&order=${orderBy}`;
|
||||
const url = `${serverURL}?where=${strParams}&keys=${strKeys}&order=${orderBy}&include=AuditTrail.UserPtr`;
|
||||
const res = await axios.get(url, { headers: headers });
|
||||
// console.log("res ", res.data?.results);
|
||||
setList(res.data?.results);
|
||||
if (id === "5Go51Q7T8r") {
|
||||
const currentUser = Parse.User.current().id;
|
||||
const listData = res.data?.results.filter(
|
||||
(x) => x.Signers.length > 0
|
||||
);
|
||||
let arr = [];
|
||||
for (const obj of listData) {
|
||||
const isSigner = obj.Signers.some(
|
||||
(item) => item.UserId.objectId === currentUser
|
||||
);
|
||||
if (isSigner) {
|
||||
let isRecord;
|
||||
if (obj?.AuditTrail && obj?.AuditTrail.length > 0) {
|
||||
isRecord = obj?.AuditTrail.some(
|
||||
(item) =>
|
||||
item?.UserPtr?.UserId?.objectId === currentUser &&
|
||||
item.Activity === "Signed"
|
||||
);
|
||||
} else {
|
||||
isRecord = false;
|
||||
}
|
||||
if (isRecord === false) {
|
||||
arr.push(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
setList(arr);
|
||||
} else {
|
||||
setList(res.data?.results);
|
||||
}
|
||||
setIsLoader(false);
|
||||
} catch (err) {
|
||||
console.log("err ", err);
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { SaveFileSize } from "../../constant/saveFileSize";
|
||||
import Parse from "parse";
|
||||
import sanitizeFileName from "../../primitives/sanitizeFileName";
|
||||
// import Parse from "parse";
|
||||
// import sanitizeFileName from "../../primitives/sanitizeFileName";
|
||||
import axios from "axios";
|
||||
|
||||
const FileUpload = (props) => {
|
||||
const [parseBaseUrl] = useState(localStorage.getItem("baseUrl"));
|
||||
@@ -11,7 +12,7 @@ const FileUpload = (props) => {
|
||||
|
||||
const [localValue, setLocalValue] = useState("");
|
||||
const [Message] = useState(false);
|
||||
const [percentage] = useState(0);
|
||||
const [percentage, setpercentage] = useState(0);
|
||||
|
||||
const REQUIRED_FIELD_SYMBOL = "*";
|
||||
|
||||
@@ -68,33 +69,50 @@ const FileUpload = (props) => {
|
||||
};
|
||||
|
||||
const handleFileUpload = async (file) => {
|
||||
Parse.serverURL = parseBaseUrl;
|
||||
Parse.initialize(parseAppId);
|
||||
const size = file.size;
|
||||
const fileName = file.name;
|
||||
const name = sanitizeFileName(fileName);
|
||||
setfileload(true);
|
||||
const pdfFile = file;
|
||||
const parseFile = new Parse.File(name, pdfFile);
|
||||
const file_url = parseBaseUrl.slice(0, -4);
|
||||
const url = `${file_url}file_upload`;
|
||||
const formData = new FormData();
|
||||
formData.append("file", file);
|
||||
const config = {
|
||||
headers: {
|
||||
"content-type": "multipart/form-data",
|
||||
"X-Parse-Application-Id": parseAppId
|
||||
},
|
||||
onUploadProgress: function (progressEvent) {
|
||||
var percentCompleted = Math.round(
|
||||
(progressEvent.loaded * 100) / progressEvent.total
|
||||
);
|
||||
setpercentage(percentCompleted);
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await parseFile.save();
|
||||
await axios
|
||||
.post(url, formData, config)
|
||||
.then((res) => {
|
||||
if (res.data.status === "Error") {
|
||||
alert(res.data.message);
|
||||
}
|
||||
setFileUpload(res.data.imageUrl);
|
||||
props.onChange(res.data.imageUrl);
|
||||
setfileload(false);
|
||||
setpercentage(0);
|
||||
|
||||
setFileUpload(response.url());
|
||||
props.onChange(response.url());
|
||||
setfileload(false);
|
||||
// The response object will contain information about the uploaded file
|
||||
// console.log("File uploaded:", response);
|
||||
|
||||
// You can access the URL of the uploaded file using response.url()
|
||||
// console.log("File URL:", response.url());
|
||||
if (response.url()) {
|
||||
SaveFileSize(size, response.url());
|
||||
|
||||
return response.url();
|
||||
}
|
||||
if (res.data.imageUrl) {
|
||||
SaveFileSize(file.size, res.data.imageUrl);
|
||||
return res.data.imageUrl;
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
alert(`${err.message}`);
|
||||
setfileload(false);
|
||||
setpercentage(0);
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Error uploading file:", error);
|
||||
alert(error.message);
|
||||
setfileload(false);
|
||||
setpercentage(0);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -106,7 +124,7 @@ const FileUpload = (props) => {
|
||||
<a
|
||||
href={props.formData}
|
||||
title={props.formData}
|
||||
style={{ paddingBottom: "10px", color: "blue" }}
|
||||
style={{ paddingBottom: "10px", color: "blue"}}
|
||||
>
|
||||
Download
|
||||
</a>
|
||||
@@ -133,12 +151,14 @@ const FileUpload = (props) => {
|
||||
<span className="required">{REQUIRED_FIELD_SYMBOL}</span>
|
||||
)}
|
||||
{fileload ? (
|
||||
<div className="progress pull-right">
|
||||
<div
|
||||
className="progress__bar"
|
||||
style={{ width: `${percentage}%` }}
|
||||
></div>
|
||||
<span className="progress__value">{percentage}%</span>
|
||||
<div className="flex items-center gap-x-2">
|
||||
<div className="h-2 rounded-full w-[200px] md:w-[400px] bg-gray-200">
|
||||
<div
|
||||
className="h-2 rounded-full bg-blue-500"
|
||||
style={{ width: `${percentage}%` }}
|
||||
></div>
|
||||
</div>
|
||||
<span className="text-black text-sm">{percentage}%</span>
|
||||
</div>
|
||||
) : (
|
||||
Message && (
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import Parse from "parse";
|
||||
export default function reportJson(id) {
|
||||
const currentUserId = Parse.User.current().id;
|
||||
// console.log("userId", currentUserId)
|
||||
// console.log("json ", json);
|
||||
|
||||
switch (id) {
|
||||
// draft documents report
|
||||
@@ -53,28 +53,7 @@ export default function reportJson(id) {
|
||||
ExpiryDate: {
|
||||
$gt: { __type: "Date", iso: new Date().toISOString() }
|
||||
},
|
||||
$and: [
|
||||
{
|
||||
"AuditTrail.UserPtr": {
|
||||
$ne: {
|
||||
__type: "Pointer",
|
||||
className: "contracts_Users",
|
||||
objectId: "CkpaR0F6mj"
|
||||
}
|
||||
}
|
||||
},
|
||||
{ "AuditTrail.Activity": { $ne: "Signed" } }
|
||||
],
|
||||
Placeholders: { $ne: null },
|
||||
Signers: {
|
||||
$in: [
|
||||
{
|
||||
__type: "Pointer",
|
||||
className: "contracts_Users",
|
||||
objectId: "CkpaR0F6mj"
|
||||
}
|
||||
]
|
||||
}
|
||||
Placeholders: { $ne: null }
|
||||
},
|
||||
keys: [
|
||||
"Name",
|
||||
@@ -82,7 +61,9 @@ export default function reportJson(id) {
|
||||
"Folder.Name",
|
||||
"URL",
|
||||
"ExtUserPtr.Name",
|
||||
"Signers.Name"
|
||||
"Signers.Name",
|
||||
"Signers.UserId",
|
||||
"AuditTrail"
|
||||
],
|
||||
orderBy: "-updatedAt",
|
||||
actions: [
|
||||
@@ -144,7 +125,12 @@ export default function reportJson(id) {
|
||||
params: {
|
||||
Type: null,
|
||||
IsCompleted: true,
|
||||
$or: [{ IsDeclined: null }, { IsDeclined: false }]
|
||||
CreatedBy: {
|
||||
__type: "Pointer",
|
||||
className: "_User",
|
||||
objectId: currentUserId
|
||||
},
|
||||
IsDeclined: { $ne: true }
|
||||
},
|
||||
keys: [
|
||||
"Name",
|
||||
@@ -210,6 +196,11 @@ export default function reportJson(id) {
|
||||
reportName: "Declined Documents",
|
||||
className: "contracts_Document",
|
||||
params: { Type: null, IsDeclined: true },
|
||||
CreatedBy: {
|
||||
__type: "Pointer",
|
||||
className: "_User",
|
||||
objectId: currentUserId
|
||||
},
|
||||
keys: [
|
||||
"Name",
|
||||
"Note",
|
||||
@@ -330,28 +321,7 @@ export default function reportJson(id) {
|
||||
ExpiryDate: {
|
||||
$gt: { __type: "Date", iso: new Date().toISOString() }
|
||||
},
|
||||
$and: [
|
||||
{
|
||||
"AuditTrail.UserPtr": {
|
||||
$ne: {
|
||||
__type: "Pointer",
|
||||
className: "contracts_Users",
|
||||
objectId: "CkpaR0F6mj"
|
||||
}
|
||||
}
|
||||
},
|
||||
{ "AuditTrail.Activity": { $ne: "Signed" } }
|
||||
],
|
||||
Placeholders: { $ne: null },
|
||||
Signers: {
|
||||
$in: [
|
||||
{
|
||||
__type: "Pointer",
|
||||
className: "contracts_Users",
|
||||
objectId: "CkpaR0F6mj"
|
||||
}
|
||||
]
|
||||
}
|
||||
Placeholders: { $ne: null }
|
||||
},
|
||||
keys: [
|
||||
"Name",
|
||||
@@ -359,7 +329,9 @@ export default function reportJson(id) {
|
||||
"Folder.Name",
|
||||
"URL",
|
||||
"ExtUserPtr.Name",
|
||||
"Signers.Name"
|
||||
"Signers.Name",
|
||||
"Signers.UserId",
|
||||
"AuditTrail"
|
||||
],
|
||||
orderBy: "-updatedAt",
|
||||
actions: [
|
||||
|
||||
@@ -27,6 +27,7 @@ const Report = () => {
|
||||
const { className, params, keys, orderBy } = json;
|
||||
Parse.serverURL = localStorage.getItem("BaseUrl12");
|
||||
Parse.initialize(localStorage.getItem("AppID12"));
|
||||
const currentUser = Parse.User.current().id;
|
||||
const serverURL =
|
||||
localStorage.getItem("BaseUrl12") + "classes/" + className;
|
||||
|
||||
@@ -38,10 +39,37 @@ const Report = () => {
|
||||
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
|
||||
};
|
||||
try {
|
||||
const url = `${serverURL}?where=${strParams}&keys=${strKeys}&order=${orderBy}`;
|
||||
const url = `${serverURL}?where=${strParams}&keys=${strKeys}&order=${orderBy}&include=AuditTrail.UserPtr`;
|
||||
const res = await axios.get(url, { headers: headers });
|
||||
// console.log("res ", res.data?.results);
|
||||
setList(res.data?.results);
|
||||
if (id === "4Hhwbp482K") {
|
||||
const listData = res.data?.results.filter(
|
||||
(x) => x.Signers.length > 0
|
||||
);
|
||||
let arr = [];
|
||||
for (const obj of listData) {
|
||||
const isSigner = obj.Signers.some(
|
||||
(item) => item.UserId.objectId === currentUser
|
||||
);
|
||||
if (isSigner) {
|
||||
let isRecord;
|
||||
if (obj?.AuditTrail && obj?.AuditTrail.length > 0) {
|
||||
isRecord = obj?.AuditTrail.some(
|
||||
(item) =>
|
||||
item?.UserPtr?.UserId?.objectId === currentUser &&
|
||||
item.Activity === "Signed"
|
||||
);
|
||||
} else {
|
||||
isRecord = false;
|
||||
}
|
||||
if (isRecord === false) {
|
||||
arr.push(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
setList(arr);
|
||||
} else {
|
||||
setList(res.data?.results);
|
||||
}
|
||||
setIsLoader(false);
|
||||
} catch (err) {
|
||||
console.log("err ", err);
|
||||
|
||||
Reference in New Issue
Block a user