feat:add contactbook report & updated version of app in footer

This commit is contained in:
prafull-opensignlabs
2023-11-24 17:12:38 +05:30
parent e4f9152de8
commit 636910a78e
13 changed files with 303 additions and 98 deletions
+3 -2
View File
@@ -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"
}
}
}
+1
View File
@@ -0,0 +1 @@
v1.0.5-beta
+15 -7
View File
@@ -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 &copy; {new Date().getFullYear()} &nbsp;
{appName}{" "}
(version:{" "}
{localStorage.getItem("appVersion") &&
`${Package.version}.${localStorage.getItem("appVersion")}`}
)
{appName} ( version: {version ? version : `${Package.version} `})
</div>
<button
className={`${
+3 -3
View File
@@ -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}
+25 -1
View File
@@ -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;
}
+160 -66
View File
@@ -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>
)
)}
</>
) : (
<></>
+15 -15
View File
@@ -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}
+4
View File
@@ -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}
+36
View File
@@ -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;
}
@@ -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"
}]
}
]