mirror of
https://github.com/OpenSignLabs/OpenSign.git
synced 2026-08-24 08:32:34 +02:00
feat: disbale validation feature, documentId,webhook,API token for free users and add upgrade button to subscribe
This commit is contained in:
@@ -3,6 +3,7 @@ import { themeColor } from "../../constant/const";
|
||||
import ModalUi from "../../primitives/ModalUi";
|
||||
import { radioButtonWidget } from "../../constant/Utils";
|
||||
import PremiumAlertHeader from "../../primitives/PremiumAlertHeader";
|
||||
import Upgrade from "../../primitives/Upgrade";
|
||||
function DropdownWidgetOption(props) {
|
||||
const [dropdownOptionList, setDropdownOptionList] = useState([
|
||||
"option-1",
|
||||
@@ -241,36 +242,59 @@ function DropdownWidgetOption(props) {
|
||||
}}
|
||||
className="fa-solid fa-square-plus"
|
||||
></i>
|
||||
{props.type === "checkbox" && !props.isSignYourself && (
|
||||
<>
|
||||
<label style={{ fontSize: "13px", fontWeight: "600" }}>
|
||||
Minimun check
|
||||
</label>
|
||||
<input
|
||||
required
|
||||
defaultValue={0}
|
||||
value={minCount}
|
||||
onChange={(e) => {
|
||||
const count = handleSetMinMax(e);
|
||||
setMinCount(count);
|
||||
}}
|
||||
className="drodown-input"
|
||||
/>
|
||||
<label style={{ fontSize: "13px", fontWeight: "600" }}>
|
||||
Maximum check
|
||||
</label>
|
||||
<input
|
||||
required
|
||||
defaultValue={0}
|
||||
value={maxCount}
|
||||
onChange={(e) => {
|
||||
const count = handleSetMinMax(e);
|
||||
setMaxCount(count);
|
||||
}}
|
||||
className="drodown-input"
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
<div>
|
||||
{props.type === "checkbox" && !props.isSignYourself && (
|
||||
<>
|
||||
<label
|
||||
style={{
|
||||
fontSize: "13px",
|
||||
fontWeight: "600",
|
||||
color: !props.isSubscribe && "gray"
|
||||
}}
|
||||
>
|
||||
Minimun check
|
||||
</label>
|
||||
{!props.isSubscribe && <Upgrade />}
|
||||
<input
|
||||
required
|
||||
defaultValue={0}
|
||||
value={minCount}
|
||||
onChange={(e) => {
|
||||
const count = handleSetMinMax(e);
|
||||
setMinCount(count);
|
||||
}}
|
||||
className={
|
||||
props.isSubscribe
|
||||
? "drodown-input"
|
||||
: "disabled drodown-input"
|
||||
}
|
||||
/>
|
||||
<label
|
||||
style={{
|
||||
fontSize: "13px",
|
||||
fontWeight: "600",
|
||||
color: !props.isSubscribe && "gray"
|
||||
}}
|
||||
>
|
||||
Maximum check
|
||||
</label>
|
||||
<input
|
||||
required
|
||||
defaultValue={0}
|
||||
value={maxCount}
|
||||
onChange={(e) => {
|
||||
const count = handleSetMinMax(e);
|
||||
setMaxCount(count);
|
||||
}}
|
||||
className={
|
||||
props.isSubscribe
|
||||
? "drodown-input"
|
||||
: "disabled drodown-input"
|
||||
}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{["dropdown", radioButtonWidget].includes(props.type) && (
|
||||
<>
|
||||
|
||||
@@ -4,6 +4,7 @@ import "../../styles/AddUser.css";
|
||||
import RegexParser from "regex-parser";
|
||||
import { textInputWidget } from "../../constant/Utils";
|
||||
import PremiumAlertHeader from "../../primitives/PremiumAlertHeader";
|
||||
import Upgrade from "../../primitives/Upgrade";
|
||||
|
||||
const WidgetNameModal = (props) => {
|
||||
const [formdata, setFormdata] = useState({
|
||||
@@ -133,10 +134,16 @@ const WidgetNameModal = (props) => {
|
||||
props.widgetName === textInputWidget) && (
|
||||
<>
|
||||
<div className="form-section">
|
||||
<label htmlFor="textvalidate" style={{ fontSize: 13 }}>
|
||||
<label
|
||||
htmlFor="textvalidate"
|
||||
className="disabled"
|
||||
style={{ fontSize: 13 }}
|
||||
>
|
||||
Validation
|
||||
</label>
|
||||
{!props.isSubscribe && <Upgrade />}
|
||||
<div
|
||||
className="disabled"
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
@@ -178,6 +185,7 @@ const WidgetNameModal = (props) => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="form-section">
|
||||
<label htmlFor="name" style={{ fontSize: 13 }}>
|
||||
Default value
|
||||
@@ -196,7 +204,10 @@ const WidgetNameModal = (props) => {
|
||||
}}
|
||||
/>
|
||||
{isValid === false && (
|
||||
<div className="warning defaultvalueWarning" style={{ fontSize: 12 }}>
|
||||
<div
|
||||
className="warning defaultvalueWarning"
|
||||
style={{ fontSize: 12 }}
|
||||
>
|
||||
<i
|
||||
className="fas fa-exclamation-circle"
|
||||
style={{ color: "#fab005", fontSize: 15 }}
|
||||
|
||||
@@ -3,6 +3,7 @@ import moment from "moment";
|
||||
import { themeColor } from "./const";
|
||||
import React from "react";
|
||||
import { rgb } from "pdf-lib";
|
||||
import Parse from "parse";
|
||||
|
||||
export const isMobile = window.innerWidth < 767;
|
||||
export const textInputWidget = "text input";
|
||||
@@ -12,6 +13,35 @@ export const openInNewTab = (url) => {
|
||||
window.open(url, "_blank", "noopener,noreferrer");
|
||||
};
|
||||
|
||||
//function to get subcripition details from Extand user class
|
||||
export async function checkIsSubscribed() {
|
||||
// const tenantId = localStorage.getItem("TenantId");
|
||||
// const users = new Parse.Query("partners_Tenant");
|
||||
// users.equalTo("objectId", tenantId);
|
||||
// const res = await users.first();
|
||||
// const jsonRes = JSON.parse(JSON.stringify(res));
|
||||
|
||||
const extClass = localStorage.getItem("Extand_Class");
|
||||
const jsonSender = JSON.parse(extClass);
|
||||
const user = await Parse.Cloud.run("getUserDetails", {
|
||||
email: jsonSender[0].Email
|
||||
});
|
||||
const freeplan = user?.get("Plan") && user?.get("Plan").plan_code;
|
||||
const billingDate =
|
||||
user?.get("Next_billing_date") && user?.get("Next_billing_date");
|
||||
if (freeplan === "freeplan") {
|
||||
return false;
|
||||
} else if (billingDate) {
|
||||
if (billingDate > new Date()) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export const color = [
|
||||
"#93a3db",
|
||||
"#e6c3db",
|
||||
|
||||
@@ -3,10 +3,11 @@ import Title from "../components/Title";
|
||||
import axios from "axios";
|
||||
import Alert from "../primitives/Alert";
|
||||
import ModalUi from "../primitives/ModalUi";
|
||||
import { rejectBtn, submitBtn } from "../constant/const";
|
||||
import { openInNewTab } from "../constant/Utils";
|
||||
import { isEnableSubscription, rejectBtn, submitBtn } from "../constant/const";
|
||||
import { checkIsSubscribed, openInNewTab } from "../constant/Utils";
|
||||
import PremiumAlertHeader from "../primitives/PremiumAlertHeader";
|
||||
import Tooltip from "../primitives/Tooltip";
|
||||
import Upgrade from "../primitives/Upgrade";
|
||||
|
||||
function GenerateToken() {
|
||||
const [parseBaseUrl] = useState(localStorage.getItem("baseUrl"));
|
||||
@@ -17,6 +18,7 @@ function GenerateToken() {
|
||||
const [isGenerate, setIsGenerate] = useState(false);
|
||||
const [isErr, setIsErr] = useState(false);
|
||||
const [isModal, setIsModal] = useState(false);
|
||||
const [isSubscribe, setIsSubscribe] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
fetchToken();
|
||||
@@ -25,6 +27,11 @@ function GenerateToken() {
|
||||
|
||||
const fetchToken = async () => {
|
||||
try {
|
||||
if (isEnableSubscription) {
|
||||
const getIsSubscribe = await checkIsSubscribed();
|
||||
setIsSubscribe(getIsSubscribe);
|
||||
}
|
||||
|
||||
const url = parseBaseUrl + "functions/getapitoken";
|
||||
const headers = {
|
||||
"Content-Type": "application/json",
|
||||
@@ -35,6 +42,7 @@ function GenerateToken() {
|
||||
if (res) {
|
||||
SetApiToken(res.data.result.result);
|
||||
}
|
||||
|
||||
setIsLoader(false);
|
||||
} catch (err) {
|
||||
SetApiToken();
|
||||
@@ -118,13 +126,29 @@ function GenerateToken() {
|
||||
) : (
|
||||
<div className="bg-white flex flex-col justify-center shadow rounded">
|
||||
<PremiumAlertHeader />
|
||||
<h1 className="ml-4 mt-3 mb-2 font-semibold">
|
||||
<h1
|
||||
className={
|
||||
isSubscribe
|
||||
? "ml-4 mt-3 mb-2 font-semibold"
|
||||
: "ml-4 mt-3 mb-2 font-semibold text-gray-300"
|
||||
}
|
||||
>
|
||||
API Token{" "}
|
||||
<Tooltip
|
||||
url={"https://docs.opensignlabs.com/docs/API-docs/opensign-api-v-1"}
|
||||
url={
|
||||
"https://docs.opensignlabs.com/docs/API-docs/opensign-api-v-1"
|
||||
}
|
||||
iconColor={!isSubscribe && "gray"}
|
||||
/>
|
||||
{!isSubscribe && <Upgrade />}
|
||||
</h1>
|
||||
<ul className="w-full flex flex-col p-2 text-sm">
|
||||
<ul
|
||||
className={
|
||||
isSubscribe
|
||||
? "w-full flex flex-col p-2 text-sm "
|
||||
: "w-full flex flex-col p-2 text-sm opacity-20 pointer-events-none"
|
||||
}
|
||||
>
|
||||
<li
|
||||
className={`flex justify-between items-center border-y-[1px] border-gray-300 break-all py-2`}
|
||||
>
|
||||
@@ -138,7 +162,13 @@ function GenerateToken() {
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
<div className="flex flex-col md:flex-row items-center justify-center gap-2 pb-4">
|
||||
<div
|
||||
className={
|
||||
isSubscribe
|
||||
? "flex flex-col md:flex-row items-center justify-center gap-2 pb-4"
|
||||
: "flex flex-col md:flex-row items-center justify-center gap-2 pb-4 opacity-40 pointer-events-none"
|
||||
}
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
onClick={apiToken ? handleModal : handleSubmit}
|
||||
|
||||
@@ -104,6 +104,7 @@ function PlaceHolderSign() {
|
||||
const [widgetName, setWidgetName] = useState(false);
|
||||
const [mailStatus, setMailStatus] = useState("");
|
||||
const [isCurrUser, setIsCurrUser] = useState(false);
|
||||
const [isSubscribe, setIsSubscribe] = useState(false);
|
||||
const [isAlreadyPlace, setIsAlreadyPlace] = useState({
|
||||
status: false,
|
||||
message: ""
|
||||
@@ -190,6 +191,7 @@ function PlaceHolderSign() {
|
||||
return true;
|
||||
} else if (billingDate) {
|
||||
if (billingDate > new Date()) {
|
||||
setIsSubscribe(true);
|
||||
return true;
|
||||
} else {
|
||||
navigate(`/subscription`);
|
||||
@@ -1617,6 +1619,7 @@ function PlaceHolderSign() {
|
||||
currWidgetsDetails={currWidgetsDetails}
|
||||
setCurrWidgetsDetails={setCurrWidgetsDetails}
|
||||
handleClose={handleNameModal}
|
||||
isSubscribe={isSubscribe}
|
||||
/>
|
||||
<DropdownWidgetOption
|
||||
type="checkbox"
|
||||
@@ -1627,6 +1630,7 @@ function PlaceHolderSign() {
|
||||
currWidgetsDetails={currWidgetsDetails}
|
||||
setCurrWidgetsDetails={setCurrWidgetsDetails}
|
||||
handleClose={handleNameModal}
|
||||
isSubscribe={isSubscribe}
|
||||
/>
|
||||
<DropdownWidgetOption
|
||||
type="dropdown"
|
||||
@@ -1637,6 +1641,7 @@ function PlaceHolderSign() {
|
||||
currWidgetsDetails={currWidgetsDetails}
|
||||
setCurrWidgetsDetails={setCurrWidgetsDetails}
|
||||
handleClose={handleNameModal}
|
||||
isSubscribe={isSubscribe}
|
||||
/>
|
||||
|
||||
{/* pdf header which contain funish back button */}
|
||||
@@ -1852,6 +1857,7 @@ function PlaceHolderSign() {
|
||||
isOpen={isNameModal}
|
||||
handleClose={handleNameModal}
|
||||
handleData={handleWidgetdefaultdata}
|
||||
isSubscribe={isSubscribe}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
|
||||
@@ -53,6 +53,7 @@ const TemplatePlaceholder = () => {
|
||||
const [isSelectListId, setIsSelectId] = useState();
|
||||
const [isSendAlert, setIsSendAlert] = useState(false);
|
||||
const [isCreateDocModal, setIsCreateDocModal] = useState(false);
|
||||
const [isSubscribe, setIsSubscribe] = useState(false);
|
||||
const [isLoading, setIsLoading] = useState({
|
||||
isLoad: true,
|
||||
message: "This might take some time"
|
||||
@@ -180,6 +181,7 @@ const TemplatePlaceholder = () => {
|
||||
return true;
|
||||
} else if (billingDate) {
|
||||
if (billingDate > new Date()) {
|
||||
setIsSubscribe(true);
|
||||
return true;
|
||||
} else {
|
||||
navigate(`/subscription`);
|
||||
@@ -1345,6 +1347,7 @@ const TemplatePlaceholder = () => {
|
||||
currWidgetsDetails={currWidgetsDetails}
|
||||
setCurrWidgetsDetails={setCurrWidgetsDetails}
|
||||
handleClose={handleNameModal}
|
||||
isSubscribe={isSubscribe}
|
||||
/>
|
||||
<DropdownWidgetOption
|
||||
type="checkbox"
|
||||
@@ -1355,6 +1358,7 @@ const TemplatePlaceholder = () => {
|
||||
currWidgetsDetails={currWidgetsDetails}
|
||||
setCurrWidgetsDetails={setCurrWidgetsDetails}
|
||||
handleClose={handleNameModal}
|
||||
isSubscribe={isSubscribe}
|
||||
/>
|
||||
<DropdownWidgetOption
|
||||
type="dropdown"
|
||||
@@ -1365,6 +1369,7 @@ const TemplatePlaceholder = () => {
|
||||
currWidgetsDetails={currWidgetsDetails}
|
||||
setCurrWidgetsDetails={setCurrWidgetsDetails}
|
||||
handleClose={handleNameModal}
|
||||
isSubscribe={isSubscribe}
|
||||
/>
|
||||
<PlaceholderCopy
|
||||
isPageCopy={isPageCopy}
|
||||
@@ -1564,6 +1569,7 @@ const TemplatePlaceholder = () => {
|
||||
isOpen={isNameModal}
|
||||
handleClose={handleNameModal}
|
||||
handleData={handleWidgetdefaultdata}
|
||||
isSubscribe={isSubscribe}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -8,6 +8,9 @@ import sanitizeFileName from "../primitives/sanitizeFileName";
|
||||
import axios from "axios";
|
||||
import PremiumAlertHeader from "../primitives/PremiumAlertHeader";
|
||||
import Tooltip from "../primitives/Tooltip";
|
||||
import { isEnableSubscription } from "../constant/const";
|
||||
import { checkIsSubscribed } from "../constant/Utils";
|
||||
import Upgrade from "../primitives/Upgrade";
|
||||
|
||||
function UserProfile() {
|
||||
const navigate = useNavigate();
|
||||
@@ -21,15 +24,24 @@ function UserProfile() {
|
||||
const [isLoader, setIsLoader] = useState(false);
|
||||
const [percentage, setpercentage] = useState(0);
|
||||
const [isDisableDocId, setIsDisableDocId] = useState(false);
|
||||
const [isSubscribe, setIsSubscribe] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
getUserDetail();
|
||||
}, []);
|
||||
|
||||
const getUserDetail = async () => {
|
||||
const extClass = localStorage.getItem("Extand_Class");
|
||||
const jsonSender = JSON.parse(extClass);
|
||||
const HeaderDocId = jsonSender[0]?.HeaderDocId;
|
||||
if (isEnableSubscription) {
|
||||
const getIsSubscribe = await checkIsSubscribed();
|
||||
setIsSubscribe(getIsSubscribe);
|
||||
}
|
||||
if (HeaderDocId) {
|
||||
setIsDisableDocId(HeaderDocId);
|
||||
}
|
||||
}, []);
|
||||
};
|
||||
const handleSubmit = async (e) => {
|
||||
e.preventDefault();
|
||||
setIsLoader(true);
|
||||
@@ -156,7 +168,6 @@ function UserProfile() {
|
||||
const handleDisableDocId = () => {
|
||||
setIsDisableDocId((prevChecked) => !prevChecked);
|
||||
};
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Title title={"Profile"} />
|
||||
@@ -263,18 +274,30 @@ function UserProfile() {
|
||||
</li>
|
||||
<li className="border-y-[1px] border-gray-300 break-all">
|
||||
<div className="flex justify-between items-center py-2">
|
||||
<span className="font-semibold">
|
||||
<span
|
||||
className={
|
||||
isSubscribe
|
||||
? "font-semibold"
|
||||
: "font-semibold text-gray-300"
|
||||
}
|
||||
>
|
||||
Disable DocumentId :{" "}
|
||||
<Tooltip
|
||||
url={
|
||||
"https://docs.opensignlabs.com/docs/help/Settings/disabledocumentid"
|
||||
}
|
||||
isSubscribe={isSubscribe}
|
||||
/>{" "}
|
||||
{!isSubscribe && <Upgrade />}
|
||||
</span>{" "}
|
||||
<label
|
||||
className={`${
|
||||
editmode ? "cursor-pointer" : ""
|
||||
} relative inline-flex items-center mb-0`}
|
||||
className={
|
||||
!isSubscribe
|
||||
? "relative inline-flex items-center mb-0 pointer-events-none opacity-50"
|
||||
: `${
|
||||
editmode ? "cursor-pointer" : ""
|
||||
} relative inline-flex items-center mb-0`
|
||||
}
|
||||
>
|
||||
<input
|
||||
disabled={editmode ? false : true}
|
||||
|
||||
@@ -3,11 +3,12 @@ import Title from "../components/Title";
|
||||
import axios from "axios";
|
||||
import Alert from "../primitives/Alert";
|
||||
import ModalUi from "../primitives/ModalUi";
|
||||
import { rejectBtn, submitBtn } from "../constant/const";
|
||||
import { openInNewTab } from "../constant/Utils";
|
||||
import { isEnableSubscription, rejectBtn, submitBtn } from "../constant/const";
|
||||
import { checkIsSubscribed, openInNewTab } from "../constant/Utils";
|
||||
import Parse from "parse";
|
||||
import PremiumAlertHeader from "../primitives/PremiumAlertHeader";
|
||||
import Tooltip from "../primitives/Tooltip";
|
||||
import Upgrade from "../primitives/Upgrade";
|
||||
|
||||
function Webhook() {
|
||||
const [parseBaseUrl] = useState(localStorage.getItem("baseUrl"));
|
||||
@@ -17,6 +18,7 @@ function Webhook() {
|
||||
const [isGenerate, setIsGenerate] = useState(false);
|
||||
const [isErr, setIsErr] = useState(false);
|
||||
const [isModal, setIsModal] = useState(false);
|
||||
const [isSubscribe, setIsSubscribe] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
fetchWebhook();
|
||||
@@ -25,6 +27,10 @@ function Webhook() {
|
||||
|
||||
const fetchWebhook = async () => {
|
||||
const email = Parse.User.current().getEmail();
|
||||
if (isEnableSubscription) {
|
||||
const getIsSubscribe = await checkIsSubscribed();
|
||||
setIsSubscribe(getIsSubscribe);
|
||||
}
|
||||
const params = { email: email };
|
||||
try {
|
||||
const extRes = await Parse.Cloud.run("getUserDetails", params);
|
||||
@@ -104,13 +110,27 @@ function Webhook() {
|
||||
) : (
|
||||
<div className="bg-white flex flex-col justify-center shadow rounded">
|
||||
<PremiumAlertHeader />
|
||||
<h1 className="ml-4 mt-3 mb-2 font-semibold">
|
||||
<h1
|
||||
className={
|
||||
isSubscribe
|
||||
? "ml-4 mt-3 mb-2 font-semibold"
|
||||
: "ml-4 mt-3 mb-2 font-semibold text-gray-300"
|
||||
}
|
||||
>
|
||||
Webhook{" "}
|
||||
<Tooltip
|
||||
url={"https://docs.opensignlabs.com/docs/API-docs/get-webhook"}
|
||||
isSubscribe={isSubscribe}
|
||||
/>
|
||||
{!isSubscribe && <Upgrade />}
|
||||
</h1>
|
||||
<ul className="w-full flex flex-col p-2 text-sm">
|
||||
<ul
|
||||
className={
|
||||
isSubscribe
|
||||
? "w-full flex flex-col p-2 text-sm "
|
||||
: "w-full flex flex-col p-2 text-sm opacity-20 pointer-events-none"
|
||||
}
|
||||
>
|
||||
<li
|
||||
className={`flex justify-between items-center border-y-[1px] border-gray-300 break-all py-2`}
|
||||
>
|
||||
@@ -120,7 +140,13 @@ function Webhook() {
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
<div className="flex flex-col md:flex-row items-center justify-center gap-2 pb-4">
|
||||
<div
|
||||
className={
|
||||
isSubscribe
|
||||
? "flex flex-col md:flex-row items-center justify-center gap-2 pb-4"
|
||||
: "flex flex-col md:flex-row items-center justify-center gap-2 pb-4 opacity-40 pointer-events-none"
|
||||
}
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleModal}
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
import React from "react";
|
||||
import { Tooltip as ReactTooltip } from "react-tooltip";
|
||||
import { openInNewTab } from "../constant/Utils";
|
||||
const Tooltip = ({ id, message, url, iconColor }) =>
|
||||
const Tooltip = ({ id, message, url, iconColor, isSubscribe }) =>
|
||||
url ? (
|
||||
<button onClick={() => openInNewTab(url)} className="text-center">
|
||||
<button
|
||||
onClick={() => openInNewTab(url)}
|
||||
className={
|
||||
isSubscribe
|
||||
? "text-center"
|
||||
: "text-center opacity-20 pointer-events-none"
|
||||
}
|
||||
>
|
||||
<sup>
|
||||
<i
|
||||
className="fa-solid fa-question rounded-full"
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import React from "react";
|
||||
|
||||
function Upgrade() {
|
||||
return (
|
||||
<sup>
|
||||
<a
|
||||
href="https://www.opensignlabs.com/plans-pricing"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-blue-800 text-sm cursor-pointer "
|
||||
>
|
||||
Upgrade now
|
||||
</a>
|
||||
</sup>
|
||||
);
|
||||
}
|
||||
|
||||
export default Upgrade;
|
||||
Reference in New Issue
Block a user