From ade97b972fa51ba20c45c9c1a5740150eebeb92b Mon Sep 17 00:00:00 2001 From: prafull-opensignlabs Date: Mon, 24 Jun 2024 15:36:51 +0530 Subject: [PATCH] feat: add tour for webhook and apitoken, update css --- .../src/components/dashboard/DashboardCard.js | 25 +- .../components/shared/fields/SelectFolder.js | 9 +- apps/OpenSign/src/json/dashboardJson.js | 4 +- apps/OpenSign/src/pages/ChangePassword.js | 9 +- apps/OpenSign/src/pages/Form.js | 2 +- apps/OpenSign/src/pages/GenerateToken.js | 290 +++++++++--------- apps/OpenSign/src/pages/Managesign.js | 208 +++++++------ apps/OpenSign/src/pages/Opensigndrive.js | 2 +- apps/OpenSign/src/pages/PageNotFound.js | 2 +- apps/OpenSign/src/pages/UserProfile.js | 2 +- apps/OpenSign/src/pages/Webhook.js | 252 +++++++-------- apps/OpenSign/src/primitives/SubscribeCard.js | 24 ++ apps/OpenSign/src/styles/managesign.css | 22 +- 13 files changed, 407 insertions(+), 444 deletions(-) create mode 100644 apps/OpenSign/src/primitives/SubscribeCard.js diff --git a/apps/OpenSign/src/components/dashboard/DashboardCard.js b/apps/OpenSign/src/components/dashboard/DashboardCard.js index 48a9f3bda..f8017ac91 100644 --- a/apps/OpenSign/src/components/dashboard/DashboardCard.js +++ b/apps/OpenSign/src/components/dashboard/DashboardCard.js @@ -261,21 +261,14 @@ const DashboardCard = (props) => { } } body = str; - await axios - .post(url, body, { headers: headers }) - .then((response) => { - try { - if (response.data.result.length > 0) { - setresponse(response.data.result[0][props.FilterData.key]); - setLoading(false); - } else { - setresponse("0"); - setLoading(false); - } - } catch (error) { - setLoading(false); - } - }); + const response = await axios.post(url, body, { headers: headers }); + if (response.data.result.length > 0) { + setresponse(response.data.result[0][props.FilterData.key]); + setLoading(false); + } else { + setresponse("0"); + setLoading(false); + } } catch (error) { setLoading(false); } @@ -338,7 +331,7 @@ const DashboardCard = (props) => { }`} >
- + {
SetIsOpen(true)} - className=" cursor-pointer rounded px-[20px] py-[20px] bg-base-100 border-[1px] border-base-200 shadow flex max-w-sm gap-8 items-center" + className="cursor-pointer rounded px-[20px] py-[20px] bg-base-100 border-[1px] border-base-200 shadow flex max-w-sm gap-8 items-center" >
@@ -194,10 +194,7 @@ const SelectFolder = ({ required, onSuccess, folderCls, isReset }) => { ? selectFolder.Name : "OpenSign™ Drive"}

-
SetIsOpen(true)} - > +
; } return ( -
- + <div className="w-full bg-base-100 text-base-content shadow rounded-box p-2"> + <Title title="Change Password" /> <div className="text-xl font-bold border-b-[1px] border-gray-300"> Change Password </div> @@ -98,7 +98,10 @@ function ChangePassword() { required /> </div> - <button type="submit" className="op-btn op-btn-primary shadow-md m-2"> + <button + type="submit" + className="op-btn op-btn-primary shadow-md mt-2" + > Change Password </button> </form> diff --git a/apps/OpenSign/src/pages/Form.js b/apps/OpenSign/src/pages/Form.js index 1ef77ff98..9404b8cd8 100644 --- a/apps/OpenSign/src/pages/Form.js +++ b/apps/OpenSign/src/pages/Form.js @@ -565,7 +565,7 @@ const Forms = (props) => { setFormData((prev) => ({ ...prev, autoreminder: !formData.autoreminder })); }; return ( - <div className="shadow-md rounded my-2 p-3 bg-base-100 text-base-content md:border-[1px] md:border-gray-600/50"> + <div className="shadow-md rounded-box my-[2px] p-3 bg-base-100 text-base-content"> <Title title={props?.title} /> {isAlert && ( <Alert type={isErr ? "danger" : "success"}> diff --git a/apps/OpenSign/src/pages/GenerateToken.js b/apps/OpenSign/src/pages/GenerateToken.js index cd0365fc7..53b4a9efe 100644 --- a/apps/OpenSign/src/pages/GenerateToken.js +++ b/apps/OpenSign/src/pages/GenerateToken.js @@ -1,7 +1,6 @@ import React, { useEffect, useState } from "react"; import Title from "../components/Title"; import axios from "axios"; -import { useNavigate } from "react-router-dom"; import Alert from "../primitives/Alert"; import ModalUi from "../primitives/ModalUi"; import { isEnableSubscription } from "../constant/const"; @@ -9,19 +8,24 @@ import { checkIsSubscribed, copytoData, openInNewTab } from "../constant/Utils"; import PremiumAlertHeader from "../primitives/PremiumAlertHeader"; import Tooltip from "../primitives/Tooltip"; import Loader from "../primitives/Loader"; +import SubscribeCard from "../primitives/SubscribeCard"; +import Tour from "reactour"; +const tourSteps = [ + { + selector: '[data-tut="apisubscribe"]', + content: "Upgrade now to generate API token" + } +]; function GenerateToken() { - const navigation = useNavigate(); const [parseBaseUrl] = useState(localStorage.getItem("baseUrl")); const [parseAppId] = useState(localStorage.getItem("parseAppId")); const [apiToken, SetApiToken] = useState(""); const [isLoader, setIsLoader] = useState(true); - const [copied, setCopied] = useState(false); - const [isGenerate, setIsGenerate] = useState(false); - const [isErr, setIsErr] = useState(false); const [isModal, setIsModal] = useState(false); const [isSubscribe, setIsSubscribe] = useState(false); - + const [isAlert, setIsAlert] = useState({ type: "success", msg: "" }); + const [isTour, setIsTour] = useState(false); useEffect(() => { fetchToken(); // eslint-disable-next-line @@ -33,7 +37,6 @@ function GenerateToken() { const getIsSubscribe = await checkIsSubscribed(); setIsSubscribe(getIsSubscribe); } - const url = parseBaseUrl + "functions/getapitoken"; const headers = { "Content-Type": "application/json", @@ -44,7 +47,6 @@ function GenerateToken() { if (res) { SetApiToken(res.data.result.result); } - setIsLoader(false); } catch (err) { SetApiToken(); @@ -54,49 +56,43 @@ function GenerateToken() { }; const handleSubmit = async (e) => { e.preventDefault(); - setIsLoader(true); - setIsModal(false); - try { - const url = parseBaseUrl + "functions/generateapitoken"; - const headers = { - "Content-Type": "application/json", - "X-Parse-Application-Id": parseAppId, - sessiontoken: localStorage.getItem("accesstoken") - }; - await axios.post(url, {}, { headers: headers }).then((res) => { + if (!isSubscribe && isEnableSubscription) { + setIsTour(true); + } else { + setIsLoader(true); + setIsModal(false); + try { + const url = parseBaseUrl + "functions/generateapitoken"; + const headers = { + "Content-Type": "application/json", + "X-Parse-Application-Id": parseAppId, + sessiontoken: localStorage.getItem("accesstoken") + }; + const res = await axios.post(url, {}, { headers: headers }); if (res) { SetApiToken(res.data.result.token); - // localStorage.setItem("apiToken", res.data.result.token); - setIsGenerate(true); - setTimeout(() => { - setIsGenerate(false); - }, 1500); - setIsLoader(false); + setIsAlert({ type: "success", msg: "Token generated successfully." }); } else { console.error("Error while generating Token"); - setIsLoader(false); - setIsErr(true); - setTimeout(() => { - setIsErr(false); - }, 1500); + setIsAlert({ type: "danger", msg: "Something went wrong." }); } - }); - } catch (error) { - setIsLoader(false); - setIsErr(true); - setTimeout(() => { - setIsErr(false); - }, 1500); - - console.log("err", error); + } catch (error) { + setIsAlert({ type: "danger", msg: "Something went wrong." }); + console.log("while generating Token", error); + } finally { + setIsLoader(false); + setTimeout(() => { + setIsAlert({ type: "success", msg: "" }); + }, 1500); + } } }; const copytoclipboard = (text) => { copytoData(text); - setCopied(true); + setIsAlert({ type: "success", msg: "Copied" }); setTimeout(() => { - setCopied(false); + setIsAlert({ type: "success", msg: "" }); }, 1500); // Reset copied state after 1.5 seconds }; const handleModal = () => setIsModal(!isModal); @@ -104,132 +100,124 @@ function GenerateToken() { return ( <React.Fragment> <Title title={"API Token"} /> - {isGenerate && ( - <Alert type="success">Token generated successfully!</Alert> + {isAlert.msg && ( + <Alert type={isAlert.type}> + <div className="ml-3">{isAlert.msg}</div> + </Alert> )} - {copied && <Alert type="success">Copied</Alert>} - {isErr && <Alert type="danger">Something went wrong!</Alert>} {isLoader ? ( <div className="flex justify-center items-center h-screen"> <Loader /> </div> ) : ( - <div className="bg-base-100 text-base-content flex flex-col justify-center shadow rounded"> - {!isEnableSubscription && <PremiumAlertHeader />} - <h1 className={"ml-4 mt-3 mb-2 font-semibold"}> - OpenSign™ API{" "} - <Tooltip - url={ - "https://docs.opensignlabs.com/docs/API-docs/opensign-api-v-1" - } - isSubscribe={true} - /> - </h1> - <ul - className={ - isSubscribe || !isEnableSubscription - ? "w-full flex flex-col p-2 text-sm " - : "w-full flex flex-col p-2 text-sm opacity-20 pointer-events-none select-none" - } - > - <li className="flex flex-col md:flex-row justify-between items-center border-y-[1px] border-gray-300 break-all py-2"> - <div className="w-full md:w-[70%] flex-col md:flex-row text-xs md:text-[15px] flex items-center gap-x-5 "> - <span className="">Api Token:</span>{" "} - <span id="token" className="md:text-end py-2 md:py-0"> - <span - className="cursor-pointer" - onClick={() => copytoclipboard(apiToken)} - > - {apiToken ? apiToken : "_____"} - </span> - <button - className="op-btn op-btn-accent op-btn-outline op-btn-sm ml-2" - onClick={() => copytoclipboard(apiToken)} - > - <i className="fa-light fa-copy"></i> - </button> - </span> - </div> - <button - onClick={apiToken ? handleModal : handleSubmit} - className="op-btn op-btn-primary" - > - {apiToken ? "Regenerate Token" : "Generate Token"} - </button> - </li> - </ul> - <div className="flex items-center justify-center "> - <button - type="button" - onClick={() => - openInNewTab( + <> + <div className="bg-base-100 text-base-content flex flex-col justify-center shadow-md rounded-box mb-3"> + {!isEnableSubscription && <PremiumAlertHeader />} + <h1 className={"ml-4 mt-3 mb-2 font-semibold"}> + OpenSign™ API{" "} + <Tooltip + url={ "https://docs.opensignlabs.com/docs/API-docs/opensign-api-v-1" - ) - } - className="op-btn op-btn-secondary my-2" + } + isSubscribe={true} + /> + </h1> + <ul + className={"w-full flex flex-col p-2 text-sm"} + // isSubscribe || !isEnableSubscription + // ? "w-full flex flex-col p-2 text-sm " + // : "w-full flex flex-col p-2 text-sm opacity-20 pointer-events-none select-none" > - View Docs - </button> - </div> - - {!isSubscribe && isEnableSubscription && ( - <> - <h1 className={"ml-4 mt-3 mb-2 font-semibold"}> - Upgrade to PRO Plan - </h1> - <ul className={"w-full flex flex-col p-2 text-sm "}> - <li - className={`flex flex-col md:flex-row justify-between items-center border-y-[1px] border-gray-300 break-all py-2`} - > - <div className="w-[70%] flex-col md:flex-row flex items-center gap-3 "> - <span className="">$29.99/month:</span>{" "} - <span id="token" className=" md:text-end cursor-pointer"> - Sign 100 docs using API. Only 0.15/docs after that. - </span> - </div> - {!isSubscribe && isEnableSubscription && ( - <button - type="button" - onClick={() => navigation("/subscription")} - className="text-xs md:text-sm shadow op-btn op-btn-outline op-btn-accent" + <li className="flex flex-col md:flex-row justify-between items-center border-y-[1px] border-gray-300 break-all py-2"> + <div className="w-full md:w-[70%] flex-col md:flex-row text-xs md:text-[15px] flex items-center gap-x-5"> + <span className="ml-1">API Token:</span>{" "} + <span + id="token" + className={`${ + isSubscribe || !isEnableSubscription + ? "bg-white/20 pointer-events-none select-none" + : "" + } md:text-end py-2 md:py-0`} + > + <span + className="cursor-pointer" + onClick={() => copytoclipboard(apiToken)} > - Upgrade Now + {apiToken ? apiToken : "_____"} + </span> + <button + className="op-btn op-btn-accent op-btn-outline op-btn-sm ml-2" + onClick={() => copytoclipboard(apiToken)} + > + <i className="fa-light fa-copy"></i> </button> - )} - </li> - </ul> - </> - )} - - <ModalUi - isOpen={isModal} - title={apiToken ? "Regenerate Token" : "Generate Token"} - handleClose={handleModal} - > - <div className="m-[20px]"> - <div className="text-lg font-normal text-base-content"> - Are you sure you want to regenerate token it will expire old - token? - </div> - <hr className="bg-[#ccc] mt-4 " /> - <div className="flex items-center mt-3 gap-2 text-white"> + </span> + </div> <button - onClick={handleSubmit} - className="op-btn op-btn-primary ml-[2px]" + onClick={apiToken ? handleModal : handleSubmit} + className="op-btn op-btn-primary" > - Yes + {apiToken ? "Regenerate Token" : "Generate Token"} </button> - <button - onClick={handleModal} - className="op-btn op-btn-secondary" - > - No - </button> - </div> + </li> + </ul> + <div className="flex items-center justify-center"> + <button + type="button" + onClick={() => + openInNewTab( + "https://docs.opensignlabs.com/docs/API-docs/opensign-api-v-1" + ) + } + className="op-btn op-btn-secondary mt-2 mb-3 px-8" + > + View Docs + </button> </div> - </ModalUi> - </div> + <ModalUi + isOpen={isModal} + title={apiToken ? "Regenerate Token" : "Generate Token"} + handleClose={handleModal} + > + <div className="m-[20px]"> + <div className="text-lg font-normal text-base-content"> + Are you sure you want to regenerate token it will expire old + token? + </div> + <hr className="bg-[#ccc] mt-4" /> + <div className="flex items-center mt-3 gap-2 text-white"> + <button + onClick={handleSubmit} + className="op-btn op-btn-primary ml-[2px]" + > + Yes + </button> + <button + onClick={handleModal} + className="op-btn op-btn-secondary" + > + No + </button> + </div> + </div> + </ModalUi> + </div> + {!isSubscribe && isEnableSubscription && ( + <div data-tut="apisubscribe"> + <SubscribeCard /> + </div> + )} + </> )} + <Tour + onRequestClose={() => setIsTour(false)} + steps={tourSteps} + isOpen={isTour} + closeWithMask={false} + disableKeyboardNavigation={["esc"]} + scrollOffset={-100} + rounded={5} + /> </React.Fragment> ); } diff --git a/apps/OpenSign/src/pages/Managesign.js b/apps/OpenSign/src/pages/Managesign.js index 7c995954c..644133bdf 100644 --- a/apps/OpenSign/src/pages/Managesign.js +++ b/apps/OpenSign/src/pages/Managesign.js @@ -237,127 +237,125 @@ const ManageSign = () => { setIsValue(true); }; return ( - <div className="relative h-full bg-base-100 text-base-content flex shadow rounded overflow-auto"> + <div className="relative h-full bg-base-100 text-base-content flex shadow-md rounded-box overflow-auto"> {isLoader && ( <div className="absolute bg-black bg-opacity-30 z-50 w-full h-full flex justify-center items-center"> <Loader /> </div> )} {isAlert?.message && <Alert type={isAlert.type}>{isAlert.message}</Alert>} - <div className="relative w-full pr-[10px]"> - <div className="m-[20px]"> - <div className="text-[20px] font-semibold mb-3">My Signature</div> + <div className="relative w-full"> + <div className="ml-[5px] my-[20px] md:m-[20px]"> + <div className="text-[20px] font-semibold m-[10px] md:m-0 mb-2"> + My Signature + </div> <div className="flex flex-col md:flex-row gap-0 md:gap-[12px]"> - <div> + <div className="relative"> + <span className="font-medium select-none flex mb-[10px] pl-[10px]"> + Signature + </span> + <input + type="file" + onChange={onImageChange} + className="filetype" + accept="image/*" + ref={imageRef} + hidden + /> <div className="relative"> - <div className="flex flex-row justify-between w-1/2 pl-[10px]"> - <div className="flex flex-row justify-around items-center gap-[10px] mb-[10px]"> - <span className="font-medium select-none">Signature</span> - <input - type="file" - onChange={onImageChange} - className="filetype" - accept="image/*" - ref={imageRef} - hidden - /> - </div> - </div> - <div className="relative"> - <div> - {image ? ( - <div className="signatureCanvas relative border-[2px] border-[#888]"> - <img - alt="signature" - src={image} - className="w-full h-full object-contain" - /> - </div> - ) : ( - <SignatureCanvas - ref={canvasRef} - penColor={penColor} - canvasProps={{ - width: "456px", - height: "180px", - className: "signatureCanvas" - }} - backgroundColor="rgb(255, 255, 255)" - onEnd={() => - handleSignatureChange(canvasRef.current.toDataURL()) - } - dotSize={1} + <div> + {image ? ( + <div className="signatureCanvas relative border-[2px] border-[#888]"> + <img + alt="signature" + src={image} + className="w-full h-full object-contain" /> - )} - <div className="penContainerDefault flex flex-row justify-between"> - <div> - {!image && ( - <div className="flex flex-row"> - {allColor.map((data, key) => { - return ( - <i - style={{ - margin: "5px", - color: data, - borderBottom: - key === 0 && penColor === "blue" - ? "2px solid blue" - : key === 1 && penColor === "red" - ? "2px solid red" - : key === 2 && penColor === "black" - ? "2px solid black" - : "2px solid white" - }} - onClick={() => { - if (key === 0) { - setPenColor("blue"); - } else if (key === 1) { - setPenColor("red"); - } else if (key === 2) { - setPenColor("black"); - } - }} - key={key} - className="fa-light fa-pen-nib" - width={20} - height={20} - ></i> - ); - })} - </div> - )} + </div> + ) : ( + <SignatureCanvas + ref={canvasRef} + penColor={penColor} + canvasProps={{ + width: "456px", + height: "180px", + className: "signatureCanvas" + }} + backgroundColor="rgb(255, 255, 255)" + onEnd={() => + handleSignatureChange(canvasRef.current.toDataURL()) + } + dotSize={1} + /> + )} + <div className="penContainerDefault flex flex-row justify-between"> + <div> + {!image && ( + <div className="flex flex-row"> + {allColor.map((data, key) => { + return ( + <i + style={{ + margin: "5px", + color: data, + borderBottom: + key === 0 && penColor === "blue" + ? "2px solid blue" + : key === 1 && penColor === "red" + ? "2px solid red" + : key === 2 && penColor === "black" + ? "2px solid black" + : "2px solid white" + }} + onClick={() => { + if (key === 0) { + setPenColor("blue"); + } else if (key === 1) { + setPenColor("red"); + } else if (key === 2) { + setPenColor("black"); + } + }} + key={key} + className="fa-light fa-pen-nib" + width={20} + height={20} + ></i> + ); + })} + </div> + )} + </div> + <div className="flex flex-row gap-2"> + <div + type="button" + className="op-link" + onClick={() => handleUploadBtn()} + > + Upload image </div> - <div className="flex flex-row gap-2"> - <div - type="button" - className="op-link" - onClick={() => handleUploadBtn()} - > - Upload image - </div> - <div - type="button" - className="op-link" - onClick={() => handleClear()} - > - Clear - </div> + <div + type="button" + className="op-link" + onClick={() => handleClear()} + > + Clear </div> </div> </div> - {warning && ( - <div className="warning signWarning text-[12px]"> - <i className="fa-light fa-exclamation-circle text-[#fab005] text-[15px] mr-[4px]"></i> - Please upload signature/Image - </div> - )} </div> + {warning && ( + <span className="customwarning signWarning text-[12px] w-[220px] md:w-[300px]"> + <i className="fa-light fa-exclamation-circle text-[#fab005] text-[15px] mr-[4px]"></i> + Please upload signature/Image + </span> + )} </div> </div> <div className="relative"> - <div className="mb-[10px]"> - <span className="font-medium select-none">Initials</span> - </div> + <span className="font-medium select-none flex mb-[10px] pl-[10px]"> + Initials + </span> <div> {isInitials ? ( <div className="intialSignature relative border-[1px] border-[#888]"> @@ -436,7 +434,7 @@ const ManageSign = () => { </div> </div> </div> - <div style={{ paddingTop: 10 }}> + <div className="pt-3 ml-2 md:ml-0"> <button className="op-btn op-btn-primary" onClick={(e) => handleSubmit(e)} diff --git a/apps/OpenSign/src/pages/Opensigndrive.js b/apps/OpenSign/src/pages/Opensigndrive.js index 0e96c3cc7..d4c2ce30d 100644 --- a/apps/OpenSign/src/pages/Opensigndrive.js +++ b/apps/OpenSign/src/pages/Opensigndrive.js @@ -522,7 +522,7 @@ function Opensigndrive() { } } return ( - <div className="bg-base-100 text-base-content rounded-xl w-full"> + <div className="bg-base-100 text-base-content rounded-box w-full shadow-md"> <Title title={"OpenSign™ Drive"} drive={true} /> <ModalUi isOpen={isAlert.isShow} diff --git a/apps/OpenSign/src/pages/PageNotFound.js b/apps/OpenSign/src/pages/PageNotFound.js index 8be661de5..1c439b27f 100644 --- a/apps/OpenSign/src/pages/PageNotFound.js +++ b/apps/OpenSign/src/pages/PageNotFound.js @@ -4,7 +4,7 @@ import Title from "../components/Title"; const PageNotFound = ({ prefix }) => { return ( - <div className="flex items-center justify-center h-screen w-full bg-base-100 text-base-content rounded"> + <div className="flex items-center justify-center h-screen w-full bg-base-100 text-base-content rounded-box"> <Title title={"Page Not Found"} /> <div className="text-center"> <h1 className="text-[60px] lg:text-[120px] font-semibold">404</h1> diff --git a/apps/OpenSign/src/pages/UserProfile.js b/apps/OpenSign/src/pages/UserProfile.js index 09d8b796d..a4099b446 100644 --- a/apps/OpenSign/src/pages/UserProfile.js +++ b/apps/OpenSign/src/pages/UserProfile.js @@ -315,7 +315,7 @@ function UserProfile() { {userNameError} </div> )} */} - <div className="bg-base-100 text-base-content flex flex-col justify-center shadow rounded-xl w-[450px]"> + <div className="bg-base-100 text-base-content flex flex-col justify-center shadow-md rounded-box w-[450px]"> <div className="flex flex-col justify-center items-center my-4"> <div className="w-[200px] h-[200px] overflow-hidden rounded-full"> <img diff --git a/apps/OpenSign/src/pages/Webhook.js b/apps/OpenSign/src/pages/Webhook.js index c414c23b3..f02c69035 100644 --- a/apps/OpenSign/src/pages/Webhook.js +++ b/apps/OpenSign/src/pages/Webhook.js @@ -1,7 +1,6 @@ import React, { useEffect, useState } from "react"; import Title from "../components/Title"; import axios from "axios"; -import { useNavigate } from "react-router-dom"; import Alert from "../primitives/Alert"; import ModalUi from "../primitives/ModalUi"; import { isEnableSubscription } from "../constant/const"; @@ -10,19 +9,24 @@ import Parse from "parse"; import PremiumAlertHeader from "../primitives/PremiumAlertHeader"; import Tooltip from "../primitives/Tooltip"; import Loader from "../primitives/Loader"; - +import SubscribeCard from "../primitives/SubscribeCard"; +import Tour from "reactour"; +const tourSteps = [ + { + selector: '[data-tut="webhooksubscribe"]', + content: "Upgrade now to set webhook" + } +]; function Webhook() { - const navigation = useNavigate(); const [parseBaseUrl] = useState(localStorage.getItem("baseUrl")); const [parseAppId] = useState(localStorage.getItem("parseAppId")); const [webhook, setWebhook] = useState(); const [isLoader, setIsLoader] = useState(true); - const [isGenerate, setIsGenerate] = useState(false); - const [isErr, setIsErr] = useState(false); const [isModal, setIsModal] = useState(false); const [isSubscribe, setIsSubscribe] = useState(false); const [error, setError] = useState(""); - + const [isAlert, setIsAlert] = useState({ type: "success", msg: "" }); + const [isTour, setIsTour] = useState(false); useEffect(() => { fetchWebhook(); // eslint-disable-next-line @@ -60,31 +64,22 @@ function Webhook() { "X-Parse-Application-Id": parseAppId, sessiontoken: localStorage.getItem("accesstoken") }; - await axios.post(url, params, { headers: headers }).then((res) => { - if (res.data && res.data.result && res.data.result.Webhook) { - setWebhook(res.data.result.Webhook); - setIsGenerate(true); - setTimeout(() => { - setIsGenerate(false); - }, 1500); - setIsLoader(false); - } else { - console.error("Error while generating webhook"); - setIsLoader(false); - setIsErr(true); - setTimeout(() => { - setIsErr(false); - }, 1500); - } - }); + const res = await axios.post(url, params, { headers: headers }); + if (res.data && res.data.result && res.data.result.Webhook) { + setWebhook(res.data.result.Webhook); + setIsAlert({ type: "success", msg: "Webhook added successfully." }); + } else { + console.error("Error while generating webhook"); + setIsAlert({ type: "danger", msg: "Something went wrong." }); + } } catch (error) { + setIsAlert({ type: "danger", msg: "Something went wrong." }); + console.log("err while generating webhook", error); + } finally { setIsLoader(false); - setIsErr(true); setTimeout(() => { - setIsErr(false); + setIsAlert({ type: "success", msg: "" }); }, 1500); - - console.log("err", error); } } else { setError("The webhook url should always start with https://"); @@ -94,131 +89,112 @@ function Webhook() { } }; - const handleModal = () => setIsModal(!isModal); + const handleModal = () => { + if (!isSubscribe && isEnableSubscription) { + setIsTour(true); + } else { + setIsModal(!isModal); + } + }; return ( <React.Fragment> <Title title={"Webhook"} /> - {isGenerate && <Alert type="success">Webhook added successfully.</Alert>} - {isErr && <Alert type="danger">Something went wrong.</Alert>} - + {isAlert.msg && <Alert type={isAlert.type}>{isAlert.msg}</Alert>} {isLoader ? ( <div className="h-[100vh] flex justify-center items-center"> <Loader /> </div> ) : ( - <div className="bg-base-100 text-base-content flex flex-col justify-center shadow rounded"> - {!isEnableSubscription && <PremiumAlertHeader />} - <h1 className={"ml-4 mt-3 mb-2 font-semibold"}> - OpenSign™ Webhook{" "} - <Tooltip - url={"https://docs.opensignlabs.com/docs/API-docs/get-webhook"} - isSubscribe={true} - /> - </h1> - <ul - className={ - isSubscribe || !isEnableSubscription - ? "w-full flex flex-col p-2 text-sm " - : "w-full flex flex-col p-2 text-sm opacity-20 pointer-events-none select-none" - } - > - <li - className={`flex flex-col md:flex-row justify-between items-center border-y-[1px] border-gray-300 break-all py-2`} - > - <div className="w-[70%] flex-col md:flex-row flex items-center gap-5 "> - <span className="">Webhook:</span>{" "} - <span id="token" className=" md:text-end cursor-pointer"> - {webhook ? webhook : "_____"} - </span> - </div> + <> + <div className="bg-base-100 text-base-content flex flex-col justify-center shadow-md rounded-box mb-3"> + {!isEnableSubscription && <PremiumAlertHeader />} + <h1 className={"ml-4 mt-3 mb-2 font-semibold"}> + OpenSign™ Webhook{" "} + <Tooltip + url={"https://docs.opensignlabs.com/docs/API-docs/get-webhook"} + isSubscribe={true} + /> + </h1> + <ul className={"w-full flex flex-col p-2 text-sm"}> + <li className="flex flex-col md:flex-row justify-between items-center border-y-[1px] border-gray-300 break-all py-2"> + <div className="w-[70%] flex-col md:flex-row flex items-center gap-5"> + <span className="">Webhook:</span>{" "} + <span id="token" className=" md:text-end cursor-pointer"> + {webhook ? webhook : "_____"} + </span> + </div> + <button + type="button" + onClick={handleModal} + className="op-btn op-btn-primary" + > + {webhook ? "Update Webhook" : "Add Webhook"} + </button> + </li> + </ul> + <div className="flex items-center justify-center"> <button type="button" - onClick={handleModal} - className="op-btn op-btn-primary " + onClick={() => + openInNewTab( + "https://docs.opensignlabs.com/docs/API-docs/save-update-webhook" + ) + } + className="op-btn op-btn-secondary mt-2 mb-3 px-7" > - {webhook ? "Update Webhook" : "Add Webhook"} + View Docs </button> - </li> - </ul> - - <div className="flex items-center justify-center "> - <button - type="button" - onClick={() => - openInNewTab( - "https://docs.opensignlabs.com/docs/API-docs/save-update-webhook" - ) - } - className="op-btn op-btn-secondary my-2" - > - View Docs - </button> - </div> - - {!isSubscribe && isEnableSubscription && ( - <> - <h1 className={"ml-4 mt-3 mb-2 font-semibold"}> - Upgrade to PRO Plan - </h1> - <ul className={"w-full flex flex-col p-2 text-sm "}> - <li - className={`flex flex-col md:flex-row justify-between items-center border-y-[1px] border-gray-300 break-all py-2`} - > - <div className="w-[70%] flex-col md:flex-row flex items-center gap-3 "> - <span className="">$29.99/month:</span>{" "} - <span id="token" className=" md:text-end cursor-pointer"> - First 100 documents included, then just $0.15 per - document. - </span> - </div> - {!isSubscribe && isEnableSubscription && ( - <button - type="button" - onClick={() => navigation("/subscription")} - className="text-xs md:text-sm shadow op-btn op-btn-outline op-btn-accent" - > - Upgrade Now - </button> - )} - </li> - </ul> - </> - )} - <ModalUi - isOpen={isModal} - title={"Regenerate Token"} - handleClose={handleModal} - > - {error && <Alert type="danger">{error}</Alert>} - <div className="m-[20px]"> - <div className="text-lg font-normal text-base-content"> - <label className="text-sm ml-2">Webhook</label> - <input - value={webhook} - onChange={(e) => setWebhook(e.target.value)} - placeholder="Enter webhook url" - className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs" - /> - </div> - <hr className="bg-[#ccc] mt-3" /> - <div className="flex items-center mt-3 gap-2"> - <button - onClick={handleSubmit} - className="op-btn op-btn-primary ml-[2px]" - > - Yes - </button> - <button - onClick={handleModal} - className="op-btn op-btn-secondary" - > - No - </button> - </div> </div> - </ModalUi> - </div> + <ModalUi + isOpen={isModal} + title={"Regenerate Token"} + handleClose={handleModal} + > + {error && <Alert type="danger">{error}</Alert>} + <div className="m-[20px]"> + <div className="text-lg font-normal text-base-content"> + <label className="text-sm ml-2">Webhook</label> + <input + value={webhook} + onChange={(e) => setWebhook(e.target.value)} + placeholder="Enter webhook url" + className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs" + /> + </div> + <hr className="bg-[#ccc] mt-3" /> + <div className="flex items-center mt-3 gap-2"> + <button + onClick={handleSubmit} + className="op-btn op-btn-primary ml-[2px]" + > + Yes + </button> + <button + onClick={handleModal} + className="op-btn op-btn-secondary" + > + No + </button> + </div> + </div> + </ModalUi> + </div> + {!isSubscribe && isEnableSubscription && ( + <div data-tut="webhooksubscribe"> + <SubscribeCard /> + </div> + )} + </> )} + <Tour + onRequestClose={() => setIsTour(false)} + steps={tourSteps} + isOpen={isTour} + closeWithMask={false} + disableKeyboardNavigation={["esc"]} + scrollOffset={-100} + rounded={5} + /> </React.Fragment> ); } diff --git a/apps/OpenSign/src/primitives/SubscribeCard.js b/apps/OpenSign/src/primitives/SubscribeCard.js new file mode 100644 index 000000000..84fdcc163 --- /dev/null +++ b/apps/OpenSign/src/primitives/SubscribeCard.js @@ -0,0 +1,24 @@ +import React from "react"; +import { useNavigate } from "react-router-dom"; + +const SubscribeCard = () => { + const navigate = useNavigate(); + return ( + <div className="op-card op-bg-primary text-primary-content w-full shadow-lg"> + <div className="op-card-body"> + <h2 className="op-card-title">Upgrade to PRO Plan</h2> + <p>$29.99/month: Sign 100 docs using API. Only $0.15/doc after that.</p> + <div className="op-card-actions justify-end"> + <button + onClick={() => navigate("/subscription")} + className="op-btn op-btn-accent" + > + Upgrade Now + </button> + </div> + </div> + </div> + ); +}; + +export default SubscribeCard; diff --git a/apps/OpenSign/src/styles/managesign.css b/apps/OpenSign/src/styles/managesign.css index a937f79b8..a32f9bb71 100644 --- a/apps/OpenSign/src/styles/managesign.css +++ b/apps/OpenSign/src/styles/managesign.css @@ -1,9 +1,8 @@ -.warning { +.customwarning { position: absolute; padding: 8px; border: 1px solid black; background: white; - width: 300px; border-radius: 5px; animation: inAnimation 2s ease-in-out; z-index: 1; @@ -35,24 +34,9 @@ visibility: hidden; } - 25% { - opacity: 1; - visibility: visible; - } - - 50% { - opacity: 1; - visibility: visible; - } - - 75% { - opacity: 1; - visibility: visible; - } - 100% { - opacity: 0; - visibility: hidden; + opacity: 1; + visibility: visible; } }