feat: update license manually

This commit is contained in:
Tristan Yang
2022-11-29 14:59:32 +08:00
parent 55f26a6077
commit 82ebe7b677
10 changed files with 136 additions and 45 deletions
+9 -4
View File
@@ -1,4 +1,4 @@
// import { useEffect } from "react";
import { useEffect } from "react";
import {
useCheckLicenseMutation,
useGetLicenseQuery,
@@ -10,12 +10,12 @@ const useLicense = () => {
const { userCount, isGuest } = useAppSelector((store) => {
return { userCount: store.users.ids.length, isGuest: store.authData.guest };
});
const { data: license } = useGetLicenseQuery(undefined, {
const { data: license, refetch: refetchLicense } = useGetLicenseQuery(undefined, {
refetchOnMountOrArgChange: true,
skip: isGuest
});
const [check, { isLoading: isChecking, isSuccess: checked }] = useCheckLicenseMutation();
const [upsert, { isSuccess: upserted, isLoading: upserting }] = useUpsertLicenseMutation();
const [upsert, { isSuccess: upserted, isLoading: upserting, reset: resetUpsert }] = useUpsertLicenseMutation();
const checkLicense = (l: string) => {
check(l);
};
@@ -28,7 +28,12 @@ const useLicense = () => {
return false;
}
};
console.log("uuu", userCount, license);
useEffect(() => {
if (upserted) {
refetchLicense();
resetUpsert();
}
}, [upserted]);
const lUserLimit = license?.user_limit ?? Number.MAX_SAFE_INTEGER;
return {
reachLimit: userCount >= lUserLimit,
+20 -6
View File
@@ -5,6 +5,7 @@ import useLicense from "../../../common/hook/useLicense";
import LicensePriceListModal from "./LicensePriceListModal";
import clsx from "clsx";
import { useTranslation } from "react-i18next";
import UpdateLicenseModal from "./UpdateLicenseModal";
interface ItemProps extends HTMLAttributes<HTMLSpanElement> { label: string, data?: string | number | string[], foldable?: boolean }
const Item = ({ label, data, foldable = false, ...rest }: ItemProps) => {
@@ -24,18 +25,20 @@ const Item = ({ label, data, foldable = false, ...rest }: ItemProps) => {
};
export default function License() {
const { t } = useTranslation("setting");
const { license: licenseInfo, reachLimit } = useLicense();
const { license: licenseInfo, reachLimit, upsertLicense, upserting, upserted } = useLicense();
const [modalVisible, setModalVisible] = useState(false);
const [updateVisible, setUpdateVisible] = useState(false);
const [base58Fold, setBase58Fold] = useState(true);
const handleRenewLicense = () => {
toggleModalVisible();
};
const toggleModalVisible = () => {
setModalVisible((prev) => !prev);
};
const toggleUpdateModalVisible = () => {
setUpdateVisible((prev) => !prev);
};
const handleLicenseValueToggle = () => {
setBase58Fold(pre => !pre);
};
return (
<>
<div className="max-w-3xl flex flex-col justify-start items-start gap-4">
@@ -48,7 +51,10 @@ export default function License() {
<Item label={t("license.value")} data={licenseInfo?.base58} foldable={base58Fold} title={base58Fold ? "Click to see full text" : "Click to fold text"}
onClick={handleLicenseValueToggle} />
</div>
<Button onClick={handleRenewLicense}>{t("license.renew")}</Button>
<div className="flex gap-2">
<Button onClick={toggleModalVisible}>{t("license.renew")}</Button>
<Button onClick={toggleUpdateModalVisible} className="ghost">{t("license.update")}</Button>
</div>
<div className="flex flex-col gap-4 bg-primary-500 text-white rounded drop-shadow-xl p-5">
<h2 className="text-2xl font-bold">{t("license.tip.title")} 🎁</h2>
<p className="text-base flex flex-col"><span>
@@ -58,7 +64,7 @@ export default function License() {
{t("license.tip.booking")} <a className="underline text-lg text-green-200" href="https://calendly.com/hansu/han-meeting" target="_blank" rel="noopener noreferrer">https://calendly.com/hansu/han-meeting</a>
</span>
<span>
{t("license.tip.wechat")}<em className="text-lg text-green-200">yanggc_2013</em>
{t("license.tip.wechat")}<em className="text-lg text-green-200">Privoce</em>
</span>
</p>
</div>
@@ -68,6 +74,14 @@ export default function License() {
closeModal={toggleModalVisible}
/>
)}
{updateVisible && (
<UpdateLicenseModal
updated={upserted}
updating={upserting}
updateLicense={upsertLicense}
closeModal={toggleUpdateModalVisible}
/>
)}
</>
);
}
@@ -16,7 +16,8 @@ interface Props {
}
const LicensePriceListModal: FC<Props> = ({ closeModal }) => {
const { t } = useTranslation(["setting", "common"]);
const { t } = useTranslation("setting");
const { t: ct } = useTranslation();
const [getUrl, { isLoading, isSuccess }] = useGetLicensePaymentUrlMutation();
const [selectPrice, setSelectPrice] = useState(
`${LicensePriceList[0].pid}|${LicensePriceList[0].limit}`
@@ -53,9 +54,9 @@ const LicensePriceListModal: FC<Props> = ({ closeModal }) => {
buttons={
<>
<Button onClick={closeModal} className="ghost">
{t("action.cancel", { ns: "common" })}
{ct("action.cancel")}
</Button>
<Button disabled={isLoading || isSuccess} onClick={handleRenew} className="danger">
<Button disabled={isLoading || isSuccess} onClick={handleRenew} >
{isLoading ? "Initialize Payment Url" : isSuccess ? "Redirecting" : t("license.renew")}
</Button>
</>
@@ -0,0 +1,56 @@
import { ChangeEvent, FC, useState, useEffect } from "react";
import toast from "react-hot-toast";
import Modal from "../../../common/component/Modal";
import StyledModal from "../../../common/component/styled/Modal";
import Button from "../../../common/component/styled/Button";
import Textarea from "../../../common/component/styled/Textarea";
import { useTranslation } from "react-i18next";
interface Props {
closeModal: () => void;
updateLicense: (param: string) => void;
updated: boolean;
updating: boolean
// domain: string;
}
const UpdateLicenseModal: FC<Props> = ({ closeModal, updateLicense, updating, updated }) => {
const [value, setValue] = useState("");
const { t } = useTranslation("setting");
const { t: ct } = useTranslation();
const handleRenew = () => {
updateLicense(value);
};
const handleLicenseUpdate = (evt: ChangeEvent<HTMLTextAreaElement>) => {
setValue(evt.target.value);
};
useEffect(() => {
if (updated) {
toast.success("Update Successfully!");
closeModal();
}
}, [updated]);
return (
<Modal id="modal-modal">
<StyledModal
buttons={
<>
<Button onClick={closeModal} className="ghost">
{ct("action.cancel")}
</Button>
<Button disabled={updating || updated || !value} onClick={handleRenew} >
{updating ? "Updating" : updated ? "Update Successfully" : t("license.update")}
</Button>
</>
}
>
<Textarea rows={18} placeholder={t("license.update_placeholder")} value={value} onChange={handleLicenseUpdate} />
</StyledModal>
</Modal>
);
};
export default UpdateLicenseModal;
+6 -6
View File
@@ -29,7 +29,7 @@ export default function Widget() {
{t('code')}:
</label>
<SyntaxHighlighter id="code" language="html" style={vscDarkPlus} className="rounded">
{`<!-- ${t('code_comment')} -->\n<script \n data-host-id="4" \n data-close-width="48" \n data-close-height="48" \n data-open-width="380" \n data-open-height="680" \n src="${location.origin}/widget.js" \n async \n/>`}
{`<!-- ${t('code_comment')} -->\n<script \n data-host-id="1" \n data-close-width="48" \n data-close-height="48" \n data-open-width="380" \n data-open-height="680" \n src="${location.origin}/widget.js" \n async \n/>`}
</SyntaxHighlighter>
<div className="text-gray-500 text-sm mt-5 mb-2">
{t('config')}:
@@ -47,23 +47,23 @@ export default function Widget() {
{[{
paramKey: "host-id",
paramDefault: 1,
remarks: "Assign the user chatting with visitor"
remarks: t("param_host")
}, {
paramKey: "close-width",
paramDefault: `48(px)`,
remarks: "The width while widget closed"
remarks: t("param_open_width")
}, {
paramKey: "close-height",
paramDefault: `48(px)`,
remarks: "The height while widget closed"
remarks: t("param_close_height")
}, {
paramKey: "open-width",
paramDefault: `380(px)`,
remarks: "The width while widget opened"
remarks: t("param_open_width")
}, {
paramKey: "open-height",
paramDefault: `680(px)`,
remarks: "The height while widget opened"
remarks: t("param_open_height")
}
].map(row => <Row key={row.paramKey} {...row} />)}
</tbody>
+1 -1
View File
@@ -78,7 +78,7 @@ const navs = [
},
{
name: "feedback",
component: "Email: han@privoce.com\nWechat: yanggc_2013"
component: "Email: han@privoce.com Wechat: Privoce"
}
]
}