diff --git a/apps/OpenSign/src/components/opensigndrive/DriveBody.js b/apps/OpenSign/src/components/opensigndrive/DriveBody.js index 213d3eac4..1a40f878b 100644 --- a/apps/OpenSign/src/components/opensigndrive/DriveBody.js +++ b/apps/OpenSign/src/components/opensigndrive/DriveBody.js @@ -385,6 +385,7 @@ function DriveBody(props) { flexDirection: "column", cursor: "pointer" }} + data-tut={props.dataTutSeventh} > no img checkPdfStatus(data)} + data-tut={props.dataTutSixth} /> {rename === data.objectId ? (
- The image displays the OpenSign logo with a stylized blue square with an open corner, accompanied by the tagline Seal the Deal, Openly. + {image && ( + The image displays the OpenSign logo with a stylized blue square with an open corner, accompanied by the tagline Seal the Deal, Openly. + )}
diff --git a/apps/OpenSign/src/pages/Opensigndrive.js b/apps/OpenSign/src/pages/Opensigndrive.js index 8c248f6cf..8a2db7ae8 100644 --- a/apps/OpenSign/src/pages/Opensigndrive.js +++ b/apps/OpenSign/src/pages/Opensigndrive.js @@ -7,6 +7,10 @@ import { useNavigate } from "react-router-dom"; import Title from "../components/Title"; import Parse from "parse"; import ModalUi from "../primitives/ModalUi"; +import TourContentWithBtn from "../primitives/TourContentWithBtn"; +import Tour from "reactour"; +import axios from "axios"; + const DriveBody = React.lazy( () => import("../components/opensigndrive/DriveBody") ); @@ -42,6 +46,8 @@ function Opensigndrive() { const [error, setError] = useState(); const [folderLoader, setIsFolderLoader] = useState(false); const [isShowSort, setIsShowSort] = useState(false); + const [isTour, setIsTour] = useState(false); + const [tourStatusArr, setTourStatusArr] = useState([]); const [isLoading, setIsLoading] = useState({ isLoad: true, message: "This might take some time" @@ -56,6 +62,8 @@ function Opensigndrive() { const [loading, setLoading] = useState(false); const sortOrder = ["Ascending", "Descending"]; const sortingValue = ["Name", "Date"]; + const [isDontShow, setIsDontShow] = useState(false); + const [tourData, setTourData] = useState(); const orderName = { Ascending: "Ascending", Descending: "Descending", @@ -73,12 +81,98 @@ function Opensigndrive() { useEffect(() => { getPdfDocumentList(); + // eslint-disable-next-line }, [docId]); + const tourConfigs = [ + { + selector: '[data-tut="reactourFirst"]', + content: () => ( + + ), + position: "top", + style: { fontSize: "13px" } + }, + { + selector: '[data-tut="reactourSecond"]', + content: () => ( + + ), + position: "top", + style: { fontSize: "13px" } + }, + { + selector: '[data-tut="reactourThird"]', + content: () => ( + + ), + position: "top", + style: { fontSize: "13px" } + }, + { + selector: '[data-tut="reactourForth"]', + content: () => ( + + ), + position: "top", + style: { fontSize: "13px" } + }, + + { + selector: '[data-tut="reactourFifth"]', + content: () => ( + + ), + position: "bottom", + style: { fontSize: "13px" } + }, + { + selector: '[data-tut="reactourSixth"]', + content: () => ( + + ), + position: "bottom", + style: { fontSize: "13px" } + }, + { + selector: '[data-tut="reactourSeventh"]', + content: () => ( + + ), + position: "bottom", + style: { fontSize: "13px" } + } + ]; //function for get all pdf document list const getPdfDocumentList = async (disbaleLoading) => { setLoading(true); + checkTourStatus(); if (!disbaleLoading) { setIsLoading({ isLoad: true, message: "This might take some time" }); } @@ -87,6 +181,22 @@ function Opensigndrive() { if (driveDetails && driveDetails === "Error: Something went wrong!") { setHandleError("Error: Something went wrong!"); } else if (driveDetails && driveDetails.length > 0) { + let newTour = tourConfigs; + const isFolderExist = driveDetails.some( + (data) => data.Type === "Folder" + ); + if (!isFolderExist) { + newTour = newTour.filter( + (data) => data.selector !== '[data-tut="reactourSeventh"]' + ); + } + const isDocumentExist = driveDetails.some((data) => data.URL); + if (!isDocumentExist) { + newTour = newTour.filter( + (data) => data.selector !== '[data-tut="reactourSixth"]' + ); + } + setTourData(newTour); setSkip((prevSkip) => prevSkip + limit); sortingData(null, null, driveDetails, true); } @@ -358,9 +468,78 @@ function Opensigndrive() { setNewFolderName(""); setError(""); }; + + const handleDontShow = (isChecked) => { + setIsDontShow(isChecked); + }; + + const closeTour = async () => { + setIsTour(false); + if (isDontShow) { + const serverUrl = localStorage.getItem("baseUrl"); + const appId = localStorage.getItem("parseAppId"); + const extUserClass = localStorage.getItem("extended_class"); + const json = JSON.parse(localStorage.getItem("Extand_Class")); + const extUserId = json && json.length > 0 && json[0].objectId; + let updatedTourStatus = []; + if (tourStatusArr.length > 0) { + updatedTourStatus = [...tourStatusArr]; + const opensignTourIndex = tourStatusArr.findIndex( + (obj) => obj["opensignTour"] === false || obj["opensignTour"] === true + ); + if (opensignTourIndex !== -1) { + updatedTourStatus[opensignTourIndex] = { opensignTour: true }; + } else { + updatedTourStatus.push({ opensignTour: true }); + } + } else { + updatedTourStatus = [{ opensignTour: true }]; + } + await axios.put( + serverUrl + "classes/" + extUserClass + "/" + extUserId, + { + TourStatus: updatedTourStatus + }, + { + headers: { + "X-Parse-Application-Id": appId + } + } + ); + } + }; + //function to use check tour status of open sign drive + async function checkTourStatus() { + const currentUser = Parse.User.current(); + const cloudRes = await Parse.Cloud.run("getUserDetails", { + email: currentUser.get("email") + }); + const res = { data: cloudRes.toJSON() }; + if (res.data && res.data.TourStatus && res.data.TourStatus.length > 0) { + const tourStatus = res.data.TourStatus; + setTourStatusArr(tourStatus); + const filteredtourStatus = tourStatus.filter( + (obj) => obj["opensignTour"] + ); + if (filteredtourStatus.length > 0) { + const opensignTour = filteredtourStatus[0]["opensignTour"]; + // console.log("loginTour", loginTour); + if (opensignTour) { + setIsTour(false); + } else { + setIsTour(true); + } + } else { + setIsTour(true); + } + } else { + setIsTour(true); + } + } return (
+ <div> <ModalUi headerColor={"#dc3545"} @@ -523,7 +702,16 @@ function Opensigndrive() { ) : ( <> <div className="folderContainer"> + <Tour + onRequestClose={closeTour} + steps={tourData} + isOpen={isTour} + closeWithMask={false} + scrollOffset={-100} + rounded={5} + /> <div + data-tut="reactourFirst" onMouseEnter={(e) => handleMouseEnter(e)} ref={scrollRef} style={{ @@ -541,7 +729,7 @@ function Opensigndrive() { } onClick={() => setIsNewFol(!isNewFol)} > - <div className="sort"> + <div className="sort" data-tut="reactourSecond"> <i className="fa fa-plus-square" aria-hidden="true" @@ -602,7 +790,11 @@ function Opensigndrive() { className={isShowSort ? "dropdown show" : "dropdown"} onClick={() => setIsShowSort(!isShowSort)} > - <div className=" sort " data-toggle="dropdown"> + <div + data-tut="reactourThird" + className=" sort " + data-toggle="dropdown" + > <i className="fa fa-sort-amount-asc" aria-hidden="true" @@ -692,7 +884,11 @@ function Opensigndrive() { ></i> </div> ) : ( - <div className="sort" onClick={() => setIsList(!isList)}> + <div + data-tut="reactourForth" + className="sort" + onClick={() => setIsList(!isList)} + > <i className="fa fa-list" aria-hidden="true" @@ -717,24 +913,28 @@ function Opensigndrive() { <span style={{ fontWeight: "bold" }}>No Data Found!</span> </div> ) : ( - <React.Suspense fallback={<Loader />}> - <DriveBody - pdfData={pdfData} - setFolderName={setFolderName} - setIsLoading={setIsLoading} - setDocId={setDocId} - getPdfDocumentList={getPdfDocumentList} - isDocId={docId} - setPdfData={setPdfData} - isList={isList} - setIsAlert={setIsAlert} - setSkip={setSkip} - sortingData={sortingData} - /> - {loading && ( - <div style={{ textAlign: "center" }}>Loading...</div> - )} - </React.Suspense> + <div data-tut="reactourFifth"> + <React.Suspense fallback={<Loader />}> + <DriveBody + dataTutSixth="reactourSixth" + dataTutSeventh="reactourSeventh" + pdfData={pdfData} + setFolderName={setFolderName} + setIsLoading={setIsLoading} + setDocId={setDocId} + getPdfDocumentList={getPdfDocumentList} + isDocId={docId} + setPdfData={setPdfData} + isList={isList} + setIsAlert={setIsAlert} + setSkip={setSkip} + sortingData={sortingData} + /> + {loading && ( + <div style={{ textAlign: "center" }}>Loading...</div> + )} + </React.Suspense> + </div> )} </> )} diff --git a/apps/OpenSign/src/pages/Report.js b/apps/OpenSign/src/pages/Report.js index 674591359..6ac3135e0 100644 --- a/apps/OpenSign/src/pages/Report.js +++ b/apps/OpenSign/src/pages/Report.js @@ -6,6 +6,7 @@ import reportJson from "../json/ReportJson"; import { useParams } from "react-router-dom"; import Title from "../components/Title"; import PageNotFound from "./PageNotFound"; +import TourContentWithBtn from "../primitives/TourContentWithBtn"; const Report = () => { const { id } = useParams(); @@ -18,6 +19,8 @@ const Report = () => { const [isNextRecord, setIsNextRecord] = useState(false); const [isMoreDocs, setIsMoreDocs] = useState(true); const [form, setForm] = useState(""); + const [tourData, setTourData] = useState([]); + const [isDontShow, setIsDontShow] = useState(false); const abortController = new AbortController(); const docPerPage = 10; @@ -46,10 +49,44 @@ const Report = () => { // eslint-disable-next-line }, [isNextRecord]); + const handleDontShow = (isChecked) => { + setIsDontShow(isChecked); + }; const getReportData = async (skipUserRecord = 0, limit = 200) => { // setIsLoader(true); const json = reportJson(id); if (json) { + if (id === "6TeaPr321t") { + const tourConfig = [ + { + selector: "[data-tut=reactourFirst]", + content: () => ( + <TourContentWithBtn + message={`onclick add button you can create new template.`} + isChecked={handleDontShow} + /> + ), + position: "top", + style: { fontSize: "13px" } + } + ]; + json.actions.map((data) => { + const newConfig = { + selector: `[data-tut="${data?.selector}"]`, + content: () => ( + <TourContentWithBtn + message={data?.message} + isChecked={handleDontShow} + /> + ), + position: "top", + style: { fontSize: "13px" } + }; + tourConfig.push(newConfig); + }); + setTourData(tourConfig); + } + setActions(json.actions); setHeading(json.heading); setReportName(json.reportName); @@ -161,6 +198,8 @@ const Report = () => { docPerPage={docPerPage} form={form} report_help={reporthelp} + tourData={tourData} + isDontShow={isDontShow} /> ) : ( <PageNotFound prefix={"Report"} /> diff --git a/apps/OpenSign/src/pages/Signup.js b/apps/OpenSign/src/pages/Signup.js index 5443f6ecf..ec8f8461a 100644 --- a/apps/OpenSign/src/pages/Signup.js +++ b/apps/OpenSign/src/pages/Signup.js @@ -533,7 +533,9 @@ const Signup = () => { <div> <div className="md:m-10 lg:m-16 md:p-4 lg:p-10 p-5 bg-[#ffffff] md:border-[1px] md:border-gray-400 "> <div className="w-[250px] h-[66px] inline-block overflow-hidden"> - <img src={image} className="object-contain h-full" alt="logo" /> + {image && ( + <img src={image} className="object-contain h-full" alt="logo" /> + )} </div> <div className="grid grid-cols-1 md:grid-cols-2 gap-x-2"> <div className=""> diff --git a/apps/OpenSign/src/primitives/GetReportDisplay.js b/apps/OpenSign/src/primitives/GetReportDisplay.js index 69aee4102..0ea1b96c5 100644 --- a/apps/OpenSign/src/primitives/GetReportDisplay.js +++ b/apps/OpenSign/src/primitives/GetReportDisplay.js @@ -3,10 +3,12 @@ import pad from "../assets/images/pad.svg"; import { useNavigate } from "react-router-dom"; import axios from "axios"; import ModalUi from "./ModalUi"; +import Tour from "reactour"; import AddSigner from "../components/AddSigner"; import { modalSubmitBtnColor, modalCancelBtnColor } from "../constant/const"; import Alert from "./Alert"; import Tooltip from "./Tooltip"; +import Parse from "parse"; const ReportTable = ({ ReportName, List, @@ -17,7 +19,9 @@ const ReportTable = ({ isMoreDocs, docPerPage, form, - report_help + report_help, + tourData, + isDontShow }) => { const navigate = useNavigate(); const [currentPage, setCurrentPage] = useState(1); @@ -27,6 +31,8 @@ const ReportTable = ({ const [isDocErr, setIsDocErr] = useState(false); const [isContactform, setIsContactform] = useState(false); const [isDeleteModal, setIsDeleteModal] = useState({}); + const [isTour, setIsTour] = useState(false); + const [tourStatusArr, setTourStatusArr] = useState([]); const startIndex = (currentPage - 1) * docPerPage; // For loop is used to calculate page numbers visible below table @@ -40,6 +46,7 @@ const ReportTable = ({ }, [List, docPerPage]); // below useEffect reset currenpage to 1 if user change route useEffect(() => { + checkTourStatus(); return () => setCurrentPage(1); }, []); @@ -146,8 +153,6 @@ const ReportTable = ({ } } ); - - // console.log("Res ", res.data); if (res.data && res.data.objectId) { setActLoader({}); setIsAlert(true); @@ -247,6 +252,74 @@ const ReportTable = ({ }; const handleCloseDeleteModal = () => setIsDeleteModal({}); + async function checkTourStatus() { + const currentUser = Parse.User.current(); + const cloudRes = await Parse.Cloud.run("getUserDetails", { + email: currentUser.get("email") + }); + const res = { data: cloudRes.toJSON() }; + if (res.data && res.data.TourStatus && res.data.TourStatus.length > 0) { + const tourStatus = res.data.TourStatus; + // console.log("res ", res.data.TourStatus); + setTourStatusArr(tourStatus); + const filteredtourStatus = tourStatus.filter( + (obj) => obj["templateTour"] + ); + if (filteredtourStatus.length > 0) { + const templateTour = filteredtourStatus[0]["templateTour"]; + + if (templateTour) { + setIsTour(false); + } else { + setIsTour(true); + } + } else { + setIsTour(true); + } + } else { + setIsTour(true); + } + } + + const closeTour = async () => { + // console.log("closeTour"); + setIsTour(false); + if (isDontShow) { + const serverUrl = localStorage.getItem("baseUrl"); + const appId = localStorage.getItem("parseAppId"); + const extUserClass = localStorage.getItem("extended_class"); + const json = JSON.parse(localStorage.getItem("Extand_Class")); + const extUserId = json && json.length > 0 && json[0].objectId; + // console.log("extUserId ", extUserId) + + let updatedTourStatus = []; + if (tourStatusArr.length > 0) { + updatedTourStatus = [...tourStatusArr]; + const templateTourIndex = tourStatusArr.findIndex( + (obj) => obj["templateTour"] === false || obj["templateTour"] === true + ); + if (templateTourIndex !== -1) { + updatedTourStatus[templateTourIndex] = { templateTour: true }; + } else { + updatedTourStatus.push({ templateTour: true }); + } + } else { + updatedTourStatus = [{ templateTour: true }]; + } + + await axios.put( + serverUrl + "classes/" + extUserClass + "/" + extUserId, + { + TourStatus: updatedTourStatus + }, + { + headers: { + "X-Parse-Application-Id": appId + } + } + ); + } + }; return ( <div className="p-2 overflow-x-scroll w-full bg-white rounded-md"> {isAlert && ( @@ -256,6 +329,16 @@ const ReportTable = ({ : "Record deleted successfully!"} </Alert> )} + {tourData && ReportName === "Templates" && ( + <Tour + onRequestClose={closeTour} + steps={tourData} + isOpen={isTour} + // rounded={5} + closeWithMask={false} + /> + )} + <div className="flex flex-row items-center justify-between my-2 mx-3 text-[20px] md:text-[23px]"> <div className="font-light"> {ReportName}{" "} @@ -267,6 +350,7 @@ const ReportTable = ({ </div> {ReportName === "Templates" && ( <i + data-tut="reactourFirst" onClick={() => navigate("/form/template")} className="fa-solid fa-square-plus text-sky-400 text-[25px]" ></i> @@ -280,6 +364,7 @@ const ReportTable = ({ </div> )} </div> + <table className="table-auto w-full border-collapse"> <thead className="text-[14px]"> <tr className="border-y-[1px]"> @@ -410,6 +495,7 @@ const ReportTable = ({ {actions?.length > 0 && actions.map((act, index) => ( <button + data-tut={act?.selector} key={index} onClick={() => act?.redirectUrl