Merge pull request #209 from XRPLF/feat/json-in-ui
Display tx json in UI inside textarea.
This commit is contained in:
115
components/Textarea.tsx
Normal file
115
components/Textarea.tsx
Normal file
@@ -0,0 +1,115 @@
|
||||
import { styled } from "../stitches.config";
|
||||
|
||||
export const Textarea = styled("textarea", {
|
||||
// Reset
|
||||
appearance: "none",
|
||||
borderWidth: "0",
|
||||
boxSizing: "border-box",
|
||||
fontFamily: "inherit",
|
||||
outline: "none",
|
||||
width: "100%",
|
||||
flex: "1",
|
||||
backgroundColor: "$mauve4",
|
||||
display: "inline-flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
borderRadius: "$sm",
|
||||
p: "$2",
|
||||
fontSize: "$md",
|
||||
lineHeight: 1,
|
||||
color: "$mauve12",
|
||||
boxShadow: `0 0 0 1px $colors$mauve8`,
|
||||
WebkitTapHighlightColor: "rgba(0,0,0,0)",
|
||||
"&::before": {
|
||||
boxSizing: "border-box",
|
||||
},
|
||||
"&::after": {
|
||||
boxSizing: "border-box",
|
||||
},
|
||||
fontVariantNumeric: "tabular-nums",
|
||||
|
||||
"&:-webkit-autofill": {
|
||||
boxShadow: "inset 0 0 0 1px $colors$blue6, inset 0 0 0 100px $colors$blue3",
|
||||
},
|
||||
|
||||
"&:-webkit-autofill::first-line": {
|
||||
fontFamily: "$untitled",
|
||||
color: "$mauve12",
|
||||
},
|
||||
|
||||
"&:focus": {
|
||||
boxShadow: `0 0 0 1px $colors$mauve10`,
|
||||
"&:-webkit-autofill": {
|
||||
boxShadow: `0 0 0 1px $colors$mauve10`,
|
||||
},
|
||||
},
|
||||
"&::placeholder": {
|
||||
color: "$mauve9",
|
||||
},
|
||||
"&:disabled": {
|
||||
pointerEvents: "none",
|
||||
backgroundColor: "$mauve2",
|
||||
color: "$mauve8",
|
||||
cursor: "not-allowed",
|
||||
"&::placeholder": {
|
||||
color: "$mauve7",
|
||||
},
|
||||
},
|
||||
|
||||
variants: {
|
||||
variant: {
|
||||
ghost: {
|
||||
boxShadow: "none",
|
||||
backgroundColor: "transparent",
|
||||
"@hover": {
|
||||
"&:hover": {
|
||||
boxShadow: "inset 0 0 0 1px $colors$mauve7",
|
||||
},
|
||||
},
|
||||
"&:focus": {
|
||||
backgroundColor: "$loContrast",
|
||||
boxShadow: `0 0 0 1px $colors$mauve10`,
|
||||
},
|
||||
"&:disabled": {
|
||||
backgroundColor: "transparent",
|
||||
},
|
||||
"&:read-only": {
|
||||
backgroundColor: "transparent",
|
||||
},
|
||||
},
|
||||
deep: {
|
||||
backgroundColor: "$deep",
|
||||
boxShadow: "none",
|
||||
},
|
||||
},
|
||||
state: {
|
||||
invalid: {
|
||||
boxShadow: "inset 0 0 0 1px $colors$crimson7",
|
||||
"&:focus": {
|
||||
boxShadow:
|
||||
"inset 0px 0px 0px 1px $colors$crimson8, 0px 0px 0px 1px $colors$crimson8",
|
||||
},
|
||||
},
|
||||
valid: {
|
||||
boxShadow: "inset 0 0 0 1px $colors$grass7",
|
||||
"&:focus": {
|
||||
boxShadow:
|
||||
"inset 0px 0px 0px 1px $colors$grass8, 0px 0px 0px 1px $colors$grass8",
|
||||
},
|
||||
},
|
||||
},
|
||||
cursor: {
|
||||
default: {
|
||||
cursor: "default",
|
||||
"&:focus": {
|
||||
cursor: "text",
|
||||
},
|
||||
},
|
||||
text: {
|
||||
cursor: "text",
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default Textarea;
|
||||
@@ -15,6 +15,7 @@ import { useSnapshot } from "valtio";
|
||||
import state from "../../state";
|
||||
import { streamState } from "../DebugStream";
|
||||
import { Button } from "..";
|
||||
import Textarea from "../Textarea";
|
||||
|
||||
interface UIProps {
|
||||
setState: (
|
||||
@@ -37,22 +38,22 @@ export const TxUI: FC<UIProps> = ({
|
||||
txFields,
|
||||
} = txState;
|
||||
|
||||
const transactionsOptions = transactionsData.map((tx) => ({
|
||||
const transactionsOptions = transactionsData.map(tx => ({
|
||||
value: tx.TransactionType,
|
||||
label: tx.TransactionType,
|
||||
}));
|
||||
|
||||
const accountOptions: SelectOption[] = accounts.map((acc) => ({
|
||||
const accountOptions: SelectOption[] = accounts.map(acc => ({
|
||||
label: acc.name,
|
||||
value: acc.address,
|
||||
}));
|
||||
|
||||
const destAccountOptions: SelectOption[] = accounts
|
||||
.map((acc) => ({
|
||||
.map(acc => ({
|
||||
label: acc.name,
|
||||
value: acc.address,
|
||||
}))
|
||||
.filter((acc) => acc.value !== selectedAccount?.value);
|
||||
.filter(acc => acc.value !== selectedAccount?.value);
|
||||
|
||||
const [feeLoading, setFeeLoading] = useState(false);
|
||||
|
||||
@@ -107,9 +108,12 @@ export const TxUI: FC<UIProps> = ({
|
||||
const specialFields = ["TransactionType", "Account", "Destination"];
|
||||
|
||||
const otherFields = Object.keys(txFields).filter(
|
||||
(k) => !specialFields.includes(k)
|
||||
k => !specialFields.includes(k)
|
||||
) as [keyof TxFields];
|
||||
|
||||
const switchToJson = () =>
|
||||
setState({ editorSavedValue: null, viewType: "json" });
|
||||
|
||||
useEffect(() => {
|
||||
const defaultOption = transactionsOptions.find(
|
||||
tt => tt.value === "Payment"
|
||||
@@ -117,7 +121,7 @@ export const TxUI: FC<UIProps> = ({
|
||||
if (defaultOption) {
|
||||
handleChangeTxType(defaultOption);
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
return (
|
||||
@@ -200,13 +204,13 @@ export const TxUI: FC<UIProps> = ({
|
||||
/>
|
||||
</Flex>
|
||||
)}
|
||||
{otherFields.map((field) => {
|
||||
{otherFields.map(field => {
|
||||
let _value = txFields[field];
|
||||
|
||||
let value: string | undefined;
|
||||
if (typeof _value === "object") {
|
||||
if (_value.$type === "json" && typeof _value.$value === "object") {
|
||||
value = JSON.stringify(_value.$value);
|
||||
value = JSON.stringify(_value.$value, null, 2);
|
||||
} else {
|
||||
value = _value.$value.toString();
|
||||
}
|
||||
@@ -214,9 +218,13 @@ export const TxUI: FC<UIProps> = ({
|
||||
value = _value?.toString();
|
||||
}
|
||||
|
||||
let isXrp = typeof _value === "object" && _value.$type === "xrp";
|
||||
|
||||
const isXrp = typeof _value === "object" && _value.$type === "xrp";
|
||||
const isJson = typeof _value === "object" && _value.$type === "json";
|
||||
const isFee = field === "Fee";
|
||||
let rows = isJson
|
||||
? (value?.match(/\n/gm)?.length || 0) + 1
|
||||
: undefined;
|
||||
if (rows && rows > 5) rows = 5;
|
||||
return (
|
||||
<Flex column key={field} css={{ mb: "$2", pr: "1px" }}>
|
||||
<Flex
|
||||
@@ -231,18 +239,30 @@ export const TxUI: FC<UIProps> = ({
|
||||
<Text muted css={{ mr: "$3" }}>
|
||||
{field + (isXrp ? " (XRP)" : "")}:{" "}
|
||||
</Text>
|
||||
<Input
|
||||
value={value}
|
||||
onChange={(e) => {
|
||||
let value = e.target.value;
|
||||
if (value && (value.includes(".") || value.includes(","))) {
|
||||
value = value.replaceAll(".", "").replaceAll(",", "");
|
||||
}
|
||||
|
||||
handleSetField(field, value);
|
||||
}}
|
||||
css={{ width: "70%", flex: "inherit" }}
|
||||
/>
|
||||
{isJson ? (
|
||||
<Textarea
|
||||
rows={rows}
|
||||
value={value}
|
||||
spellCheck={false}
|
||||
onChange={switchToJson}
|
||||
css={{
|
||||
width: "70%",
|
||||
flex: "inherit",
|
||||
resize: "vertical",
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<Input
|
||||
value={value}
|
||||
onChange={e => {
|
||||
handleSetField(field, e.target.value);
|
||||
}}
|
||||
css={{
|
||||
width: "70%",
|
||||
flex: "inherit",
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{isFee && (
|
||||
<Button
|
||||
size="xs"
|
||||
|
||||
Reference in New Issue
Block a user