feat: license setting

This commit is contained in:
Tristan Yang
2022-07-11 20:24:00 +08:00
parent 45a147ae67
commit cb80f87033
5 changed files with 164 additions and 2 deletions
+20 -2
View File
@@ -13,7 +13,8 @@ import {
CreateAdminDTO,
SMTPConfig,
AgoraConfig,
GithubAuthConfig
GithubAuthConfig,
LicenseResponse
} from "../../types/server";
const defaultExpireDuration = 7 * 24 * 60 * 60;
@@ -192,6 +193,21 @@ export const serverApi = createApi({
query: () => ({
url: `/admin/system/initialized`
})
}),
checkLicense: builder.mutation<LicenseResponse, string>({
query: (license) => ({
url: "/license/check",
method: "POST",
body: { license }
})
}),
upsertLicense: builder.mutation<boolean, string>({
query: (license) => ({
url: "/license/save",
method: "POST",
body: { license }
})
})
})
});
@@ -223,5 +239,7 @@ export const {
useGetThirdPartySecretQuery,
useUpdateThirdPartySecretMutation,
useCreateAdminMutation,
useGetInitializedQuery
useGetInitializedQuery,
useUpsertLicenseMutation,
useCheckLicenseMutation
} = serverApi;
+36
View File
@@ -0,0 +1,36 @@
import { useEffect } from "react";
import { useCheckLicenseMutation, useUpsertLicenseMutation } from "../../app/services/server";
const useLicense = (license?: string) => {
const [check, { data, isLoading: isChecking, isSuccess: checked }] = useCheckLicenseMutation();
const [upsert, { isSuccess: upserted, isLoading: upserting }] = useUpsertLicenseMutation();
const checkLicense = (l: string) => {
check(l);
};
const upsertLicense = async (l: string) => {
// check first
const resp = await check(l);
if ("data" in resp && resp.data.sign) {
return await upsert(l);
} else {
return false;
}
};
useEffect(() => {
if (license) {
checkLicense(license);
}
}, [license]);
return {
validInfo: data,
checked,
checking: isChecking,
upserting,
upserted,
checkLicense,
upsertLicense
};
};
export default useLicense;
+96
View File
@@ -0,0 +1,96 @@
import { ChangeEvent, useState } from "react";
import styled from "styled-components";
import Tippy from "@tippyjs/react";
import toast from "react-hot-toast";
import { hideAll } from "tippy.js";
import Textarea from "../../common/component/styled/Textarea";
import Button from "../../common/component/styled/Button";
import useLicense from "../../common/hook/useLicense";
const StyledConfirm = styled.div`
padding: 12px;
border-radius: 10px;
border: 1px solid orange;
background-color: #fff;
display: flex;
flex-direction: column;
gap: 10px;
width: 250px;
.tip {
color: orange;
font-size: 12px;
line-height: 1.5;
}
.btns {
display: flex;
width: 100%;
justify-content: flex-end;
gap: 14px;
}
`;
const Styled = styled.div`
max-width: 500px;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: flex-start;
gap: 15px;
> .input {
width: 100%;
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 8px;
}
`;
export default function License() {
const { checking, upserting, upsertLicense } = useLicense();
const [license, setLicense] = useState("");
const handleUpsert = async () => {
if (!license) {
toast.error("License Empty");
hideAll();
return;
}
const success = await upsertLicense(license);
if (!success) {
toast.error("Invalid License");
hideAll();
} else {
toast.success("License Updated!");
}
};
const handleLicenseInput = (evt: ChangeEvent<HTMLTextAreaElement>) => {
setLicense(evt.target.value);
};
const disableBtn = checking || upserting || !license;
return (
<Styled>
<div className="input">
<Textarea rows={10} id="license" value={license} onChange={handleLicenseInput} />
</div>
<Tippy
interactive
placement="bottom-start"
trigger="click"
content={
<StyledConfirm>
<div className="tip">Are you sure to update License?</div>
<div className="btns">
<Button onClick={() => hideAll()} className="cancel small">
Cancel
</Button>
<Button disabled={disableBtn} className="small danger" onClick={handleUpsert}>
Yes
</Button>
</div>
</StyledConfirm>
}
>
<Button disabled={disableBtn}>Save License</Button>
</Tippy>
</Styled>
);
}
+6
View File
@@ -4,6 +4,7 @@ import Logins from "./config/Logins";
import ConfigFirebase from "./config/Firebase";
import ConfigSMTP from "./config/SMTP";
import APIConfig from "./APIConfig";
import License from "./License";
import ManageMembers from "../../common/component/ManageMembers";
import FAQ from "../../common/component/FAQ";
import ConfigAgora from "./config/Agora";
@@ -63,6 +64,11 @@ const navs = [
name: "api",
title: "Third-party APP",
component: <APIConfig />
},
{
name: "license",
title: "License",
component: <License />
}
],
admin: true
+6
View File
@@ -58,6 +58,12 @@ export interface LoginConfig {
metamask: boolean;
third_party: boolean;
}
export interface LicenseResponse {
domain: string;
created_at: string;
expired_at: string;
sign: boolean;
}
export interface CreateAdminDTO extends Pick<User, "email" | "name" | "gender"> {
password: string;
}