mirror of
https://github.com/XRPLF/xrpl-dev-portal.git
synced 2025-12-01 00:55:50 +00:00
Re-level non-docs content to top of repo and rename content→docs
This commit is contained in:
156
resources/dev-tools/components/TransactionButton.tsx
Normal file
156
resources/dev-tools/components/TransactionButton.tsx
Normal file
@@ -0,0 +1,156 @@
|
||||
import * as React from 'react';
|
||||
import { useState } from 'react'
|
||||
import { useTranslate } from '@portal/hooks';
|
||||
import { clsx } from 'clsx'
|
||||
|
||||
import { type Transaction, type Wallet } from 'xrpl'
|
||||
|
||||
import { SubmitConstData, submitAndUpdateUI, canSendTransaction } from '../utils';
|
||||
|
||||
|
||||
export interface TransactionButtonProps {
|
||||
submitConstData: SubmitConstData,
|
||||
connectionReady: boolean,
|
||||
transaction: Transaction,
|
||||
sendingWallet: Wallet | undefined
|
||||
id: string, // Used to set all ids within component
|
||||
content: {
|
||||
buttonText: string,
|
||||
units: string, // Displays after the input number
|
||||
longerDescription: React.JSX.Element // JSX allows for embedding links within the longer description
|
||||
buttonTitle?: string // Only used while loading bar is activated
|
||||
},
|
||||
inputSettings?: {
|
||||
defaultValue: number, // Should NOT be a dynamic number
|
||||
setInputValue: React.Dispatch<React.SetStateAction<number>>,
|
||||
min: number,
|
||||
max: number,
|
||||
},
|
||||
loadingBar?: {
|
||||
id: string,
|
||||
widthPercent: number,
|
||||
description: string,
|
||||
defaultOn: boolean,
|
||||
},
|
||||
checkBox?: {
|
||||
setCheckValue: React.Dispatch<React.SetStateAction<boolean>>,
|
||||
defaultValue: boolean,
|
||||
description: string,
|
||||
}
|
||||
customOnClick?: Function
|
||||
}
|
||||
|
||||
function shouldDisableButton(
|
||||
connectionReady: boolean,
|
||||
sendingWallet: Wallet | undefined,
|
||||
waitingForTransaction: boolean,
|
||||
loadingBar?: {
|
||||
widthPercent: number
|
||||
}
|
||||
): boolean {
|
||||
return !canSendTransaction(connectionReady, sendingWallet?.address)
|
||||
|| waitingForTransaction
|
||||
|| (!!(loadingBar?.widthPercent) && loadingBar.widthPercent < 100)
|
||||
}
|
||||
|
||||
export function TransactionButton({
|
||||
id,
|
||||
submitConstData,
|
||||
connectionReady,
|
||||
transaction,
|
||||
sendingWallet,
|
||||
content,
|
||||
inputSettings,
|
||||
loadingBar,
|
||||
checkBox,
|
||||
customOnClick
|
||||
}: TransactionButtonProps ) {
|
||||
const { translate } = useTranslate()
|
||||
|
||||
const [waitingForTransaction, setWaitingForTransaction] = useState(false)
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="form-group" id={id}>
|
||||
|
||||
{/* Optional loading bar - Used for Partial Payments setup and EscrowFinish wait time */}
|
||||
{loadingBar?.id && <div className="progress mb-1" id={loadingBar?.id ?? ""}>
|
||||
<div className={
|
||||
clsx("progress-bar progress-bar-striped w-0",
|
||||
(loadingBar?.widthPercent < 100 && loadingBar?.widthPercent > 0) && "progress-bar-animated")}
|
||||
style={{width: (Math.min(loadingBar?.widthPercent + (loadingBar?.defaultOn ? 1 : 0), 100)).toString() + "%",
|
||||
display: (loadingBar?.widthPercent >= 100) ? 'none' : ''}}>
|
||||
|
||||
</div>
|
||||
{(loadingBar?.widthPercent < 100 && loadingBar?.widthPercent > 0 || (loadingBar.defaultOn && loadingBar?.widthPercent === 0))
|
||||
&& <small className="justify-content-center d-flex position-absolute w-100">
|
||||
{translate(loadingBar?.description)}
|
||||
</small>}
|
||||
</div>}
|
||||
|
||||
<div className="input-group mb-3">
|
||||
|
||||
{/* Loading icon for when transaction is being submitted */}
|
||||
<div className="input-group-prepend">
|
||||
<span className="input-group-text loader" style={{display: waitingForTransaction ? '' : 'none'}}>
|
||||
<img className="throbber" src="/img/xrp-loader-96.png" alt={translate("(loading)")} />
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<button className={clsx("btn btn-primary form-control needs-connection",
|
||||
(shouldDisableButton(connectionReady, sendingWallet, waitingForTransaction, loadingBar) && "disabled"))}
|
||||
type="button" id={id + "_btn"}
|
||||
disabled={shouldDisableButton(connectionReady, sendingWallet, waitingForTransaction, loadingBar)}
|
||||
onClick={async () => {
|
||||
setWaitingForTransaction(true)
|
||||
customOnClick ? await customOnClick() : await submitAndUpdateUI(submitConstData, sendingWallet!, transaction)
|
||||
setWaitingForTransaction(false)
|
||||
}}
|
||||
title={(loadingBar && (loadingBar.widthPercent > 0 && loadingBar.widthPercent < 100)) ? translate(content.buttonTitle) : ""}
|
||||
>
|
||||
{translate(content.buttonText)}
|
||||
</button>
|
||||
|
||||
{inputSettings &&
|
||||
<input id={id + "_amount"} className="form-control" type="number"
|
||||
aria-describedby={id + "amount_help"}
|
||||
defaultValue={inputSettings?.defaultValue}
|
||||
min={inputSettings?.min}
|
||||
max={inputSettings?.max}
|
||||
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
// Enforce min / max values
|
||||
let { value, min, max } = event.target;
|
||||
const newValue = Math.max(Number(min), Math.min(Number(max), Number(value)));
|
||||
// Share the value so other logic can update based on it
|
||||
inputSettings?.setInputValue(newValue)
|
||||
}
|
||||
} />}
|
||||
|
||||
{inputSettings && <div className="input-group-append">
|
||||
<span className="input-group-text" id={id + "_help"}>
|
||||
{translate(content.units)}
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
{/* Used for Escrow */}
|
||||
{checkBox && <span className="input-group-text">
|
||||
(
|
||||
<input type="checkbox"
|
||||
id={id + "_checkbox"}
|
||||
defaultValue={checkBox.defaultValue ? 1 : 0}
|
||||
onChange={(event: React.ChangeEvent<HTMLInputElement>) => checkBox.setCheckValue(event.target.checked)} />
|
||||
<label className="form-check-label" htmlFor={id + "_checkbox"}>
|
||||
{translate(checkBox.description)}
|
||||
</label>)
|
||||
</span>}
|
||||
</div>
|
||||
|
||||
<small className="form-text text-muted">
|
||||
{content.longerDescription}
|
||||
</small>
|
||||
|
||||
</div>
|
||||
<hr />
|
||||
</div>)
|
||||
}
|
||||
Reference in New Issue
Block a user