Standardize button with VoidButton

This commit is contained in:
Kieran 2022-03-14 22:57:05 +00:00
parent 3d8dba9eae
commit 20d32ad6d3
Signed by: Kieran
GPG Key ID: DE71CEB3925BE941
8 changed files with 39 additions and 50 deletions

View File

@ -4,6 +4,7 @@ import {PaywallServices} from "./Const";
import {useState} from "react";
import {LightningPaywall} from "./LightningPaywall";
import {useApi} from "./Api";
import {VoidButton} from "./VoidButton";
export function FilePaywall(props) {
const {Api} = useApi();
@ -14,15 +15,11 @@ export function FilePaywall(props) {
const [order, setOrder] = useState();
async function fetchOrder(e) {
if(e.target.classList.contains("disabled")) return;
e.target.classList.add("disabled");
async function fetchOrder() {
let req = await Api.createOrder(file.id);
if (req.ok && req.status === 200) {
setOrder(await req.json());
}
e.target.classList.remove("disabled");
}
function reset() {
@ -42,7 +39,7 @@ export function FilePaywall(props) {
<h3>
You must pay {FormatCurrency(pw.cost.amount, pw.cost.currency)} to view this file.
</h3>
<div className="btn" onClick={fetchOrder}>Pay</div>
<VoidButton onClick={fetchOrder}>Pay</VoidButton>
</div>
);
} else {

View File

@ -1,14 +1,12 @@
import {Fragment, useEffect, useState} from "react";
import {Fragment} from "react";
import FeatherIcon from "feather-icons-react";
import {FormatBytes} from "./Util";
import "./GlobalStats.css";
import {useApi} from "./Api";
import moment from "moment";
import {useSelector} from "react-redux";
export function GlobalStats(props) {
const {Api} = useApi();
export function GlobalStats() {
let stats = useSelector(state => state.info.stats);
return (

View File

@ -3,8 +3,8 @@ import {useDispatch, useSelector} from "react-redux";
import {setAuth} from "./LoginState";
import {useApi} from "./Api";
import "./Login.css";
import {btnDisable, btnEnable} from "./Util";
import HCaptcha from "@hcaptcha/react-hcaptcha";
import {VoidButton} from "./VoidButton";
export function Login() {
const {Api} = useApi();
@ -15,8 +15,7 @@ export function Login() {
const captchaKey = useSelector(state => state.info.stats.captchaSiteKey);
const dispatch = useDispatch();
async function login(e, fnLogin) {
if(!btnDisable(e.target)) return;
async function login(fnLogin) {
setError(null);
let req = await fnLogin(username, password, captchaResponse);
@ -28,8 +27,6 @@ export function Login() {
setError(rsp.error);
}
}
btnEnable(e.target);
}
return (
@ -42,8 +39,8 @@ export function Login() {
<dd><input type="password" onChange={(e) => setPassword(e.target.value)}/></dd>
</dl>
{captchaKey ? <HCaptcha sitekey={captchaKey} onVerify={setCaptchaResponse}/> : null}
<div className="btn" onClick={(e) => login(e, Api.login)}>Login</div>
<div className="btn" onClick={(e) => login(e, Api.register)}>Register</div>
<VoidButton onClick={() => login(Api.login)}>Login</VoidButton>
<VoidButton onClick={() => login(Api.register)}>Register</VoidButton>
{error ? <div className="error-msg">{error}</div> : null}
</div>
);

View File

@ -1,15 +1,13 @@
import FeatherIcon from "feather-icons-react";
import {useState} from "react";
import {btnDisable, btnEnable} from "./Util";
import {VoidButton} from "./VoidButton";
export function NoPaywallConfig(props) {
const [saveStatus, setSaveStatus] = useState();
const privateFile = props.privateFile;
const onSaveConfig = props.onSaveConfig;
async function saveConfig(e) {
if(!btnDisable(e.target)) return;
async function saveConfig() {
let cfg = {
editSecret: privateFile.metadata.editSecret
};
@ -17,12 +15,11 @@ export function NoPaywallConfig(props) {
if (typeof onSaveConfig === "function") {
setSaveStatus(await onSaveConfig(cfg));
}
btnEnable(e.target);
}
return (
<div>
<div className="btn" onClick={saveConfig}>Save</div>
<VoidButton onClick={saveConfig}>Save</VoidButton>
{saveStatus ? <FeatherIcon icon={saveStatus === true ? "check-circle" : "alert-circle"}/> : null}
</div>
)

View File

@ -6,10 +6,11 @@ import "./Profile.css";
import {useDispatch, useSelector} from "react-redux";
import {logout, setProfile as setGlobalProfile} from "./LoginState";
import {DigestAlgo} from "./FileUpload";
import {btnDisable, btnEnable, buf2hex, hasFlag} from "./Util";
import {buf2hex, hasFlag} from "./Util";
import moment from "moment";
import FeatherIcon from "feather-icons-react";
import {FileList} from "./FileList";
import {VoidButton} from "./VoidButton";
export function Profile() {
const [profile, setProfile] = useState();
@ -93,8 +94,6 @@ export function Profile() {
}
async function saveUser(e) {
if (!btnDisable(e.target)) return;
let r = await Api.updateUser({
id: profile.id,
avatar: profile.avatar,
@ -106,19 +105,15 @@ export function Profile() {
dispatch(setGlobalProfile(profile));
setSaved(true);
}
btnEnable(e.target);
}
async function submitCode(e) {
if (!btnDisable(e.target)) return;
let r = await Api.submitVerifyCode(profile.id, emailCode);
if (r.ok) {
await loadProfile();
} else {
setEmailCodeError("Invalid or expired code.");
}
btnEnable(e.target);
}
async function sendNewCode() {
@ -138,8 +133,8 @@ export function Profile() {
<br/>
<input type="text" placeholder="Verification code" value={emailCode}
onChange={(e) => setEmailCode(e.target.value)}/>
<div className="btn" onClick={submitCode}>Submit</div>
<div className="btn" onClick={() => dispatch(logout())}>Logout</div>
<VoidButton onClick={submitCode}>Submit</VoidButton>
<VoidButton onClick={() => dispatch(logout())}>Logout</VoidButton>
<br/>
{emailCodeError ? <b>{emailCodeError}</b> : null}
{emailCodeError && !newCodeSent ? <a onClick={sendNewCode}>Send verfication email</a> : null}
@ -165,13 +160,13 @@ export function Profile() {
</dl>
<div className="flex flex-center">
<div>
<div className="btn" onClick={saveUser}>Save</div>
<VoidButton onClick={saveUser}>Save</VoidButton>
</div>
<div>
{saved ? <FeatherIcon icon="check-circle"/> : null}
</div>
<div>
<div className="btn" onClick={() => dispatch(logout())}>Logout</div>
<VoidButton onClick={() => dispatch(logout())}>Logout</VoidButton>
</div>
</div>
</Fragment>

View File

@ -1,7 +1,7 @@
import {useState} from "react";
import FeatherIcon from "feather-icons-react";
import {PaywallCurrencies} from "./Const";
import {btnDisable, btnEnable} from "./Util";
import {VoidButton} from "./VoidButton";
export function StrikePaywallConfig(props) {
const file = props.file;
@ -16,8 +16,6 @@ export function StrikePaywallConfig(props) {
const [saveStatus, setSaveStatus] = useState();
async function saveStrikeConfig(e) {
if(!btnDisable(e.target)) return;
let cfg = {
editSecret,
strike: {
@ -37,7 +35,6 @@ export function StrikePaywallConfig(props) {
setSaveStatus(false);
}
}
btnEnable(e.target);
}
return (
@ -57,7 +54,7 @@ export function StrikePaywallConfig(props) {
<dt>Price:</dt>
<dd><input type="number" value={price} onChange={(e) => setPrice(parseFloat(e.target.value))}/></dd>
</dl>
<div className="btn" onClick={saveStrikeConfig}>Save</div>
<VoidButton onClick={saveStrikeConfig}>Save</VoidButton>
{saveStatus ? <FeatherIcon icon="check-circle"/> : null}
</div>
);

View File

@ -80,13 +80,3 @@ export function FormatCurrency(value, currency) {
export function hasFlag(value, flag) {
return (value & flag) === flag;
}
export function btnDisable(btn){
if(btn.classList.contains("disabled")) return false;
btn.classList.add("disabled");
return true;
}
export function btnEnable(btn){
btn.classList.remove("disabled");
}

View File

@ -0,0 +1,18 @@
export function VoidButton(props) {
async function handleClick(e) {
if (e.target.classList.contains("disabled")) return;
e.target.classList.add("disabled");
let fn = props.onClick;
if (typeof fn === "function") {
let ret = fn(e);
if (typeof ret === "object" && typeof ret.then === "function") {
await ret;
}
}
e.target.classList.remove("disabled");
}
return <div className="btn" onClick={handleClick}>{props.children}</div>;
}