Files
xrpl-hooks-ide/components/Transaction/json.tsx
2022-05-04 16:57:32 +05:30

116 lines
3.3 KiB
TypeScript

import Editor, { loader } from "@monaco-editor/react";
import { FC, useEffect, useState } from "react";
import { useTheme } from "next-themes";
import dark from "../../theme/editor/amy.json";
import light from "../../theme/editor/xcode_default.json";
import { useSnapshot } from "valtio";
import state, { parseJSON, prepareState, TransactionState } from "../../state";
import Text from "../Text";
import Flex from "../Flex";
import { Link } from "..";
import { showAlert } from "../../state/actions/showAlert";
loader.config({
paths: {
vs: "https://cdn.jsdelivr.net/npm/monaco-editor@0.30.1/min/vs",
},
});
interface JsonProps {
value?: string;
header?: string;
setState: (pTx?: Partial<TransactionState> | undefined) => void;
state: TransactionState;
}
export const TxJson: FC<JsonProps> = ({
value = "",
state: txState,
header,
setState,
}) => {
const { editorSettings } = useSnapshot(state);
const { editorValue = value } = txState;
const { theme } = useTheme();
const [hasUnsaved, setHasUnsaved] = useState(false);
useEffect(() => {
setState({ editorValue: value });
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [value]);
useEffect(() => {
if (editorValue === value) setHasUnsaved(false);
else setHasUnsaved(true);
}, [editorValue, value]);
const saveState = (value: string, txState: TransactionState) => {
const tx = prepareState(value, txState);
if (tx) setState(tx);
};
const discardChanges = () => {
showAlert("Confirm", {
body: "Are you sure to discard these changes?",
confirmText: "Yes",
onConfirm: () => setState({ editorValue: value }),
});
};
const onExit = (value: string) => {
const options = parseJSON(value);
if (options) {
saveState(value, txState);
return;
}
showAlert("Error!", {
body: `Malformed Transaction in ${header}, would you like to discard these changes?`,
confirmText: "Discard",
onConfirm: () => setState({ editorValue: value }),
onCancel: () => setState({ viewType: "json", editorSavedValue: value }),
});
};
const path = `file:///${header}`;
return (
<Flex
fluid
column
css={{ height: "calc(100% - 45px)", position: "relative" }}
>
<Editor
className="hooks-editor"
language={"json"}
path={path}
height="100%"
beforeMount={monaco => {
monaco.editor.defineTheme("dark", dark as any);
monaco.editor.defineTheme("light", light as any);
}}
value={editorValue}
onChange={val => setState({ editorValue: val })}
onMount={(editor, monaco) => {
editor.updateOptions({
minimap: { enabled: false },
glyphMargin: true,
tabSize: editorSettings.tabSize,
dragAndDrop: true,
fontSize: 14,
});
const model = editor.getModel();
model?.onWillDispose(() => onExit(model.getValue()));
}}
theme={theme === "dark" ? "dark" : "light"}
/>
{hasUnsaved && (
<Text muted small css={{ position: "absolute", bottom: 0, right: 0 }}>
This file has unsaved changes.{" "}
<Link onClick={() => saveState(editorValue, txState)}>save</Link>{" "}
<Link onClick={discardChanges}>discard</Link>
</Text>
)}
</Flex>
);
};