Merge pull request #288 from XRPLF/fix/tx
Fix tx json saving and discarding.
This commit is contained in:
		@@ -93,15 +93,29 @@ const Transaction: FC<TransactionProps> = ({ header, state: txState, ...props })
 | 
			
		||||
    }
 | 
			
		||||
  }, [selectedAccount?.value, selectedTransaction?.value, setState, txIsLoading])
 | 
			
		||||
 | 
			
		||||
  const getJsonString = useCallback(
 | 
			
		||||
    (state?: Partial<TransactionState>) =>
 | 
			
		||||
      JSON.stringify(prepareOptions?.(state) || {}, null, editorSettings.tabSize),
 | 
			
		||||
    [editorSettings.tabSize, prepareOptions]
 | 
			
		||||
  )
 | 
			
		||||
 | 
			
		||||
  const saveEditorState = useCallback(
 | 
			
		||||
    (value: string = '', transactionType?: string) => {
 | 
			
		||||
      const pTx = prepareState(value, transactionType)
 | 
			
		||||
      if (pTx) {
 | 
			
		||||
        pTx.editorValue = getJsonString(pTx)
 | 
			
		||||
        return setState(pTx)
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    [getJsonString, setState]
 | 
			
		||||
  )
 | 
			
		||||
 | 
			
		||||
  const submitTest = useCallback(async () => {
 | 
			
		||||
    let st: TransactionState | undefined
 | 
			
		||||
    const tt = txState.selectedTransaction?.value
 | 
			
		||||
    if (viewType === 'json') {
 | 
			
		||||
      // save the editor state first
 | 
			
		||||
      const pst = prepareState(editorValue || '', tt)
 | 
			
		||||
      if (!pst) return
 | 
			
		||||
 | 
			
		||||
      st = setState(pst)
 | 
			
		||||
      st = saveEditorState(editorValue, tt)
 | 
			
		||||
      if (!st) return
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const account = accounts.find(acc => acc.address === selectedAccount?.value)
 | 
			
		||||
@@ -132,23 +146,18 @@ const Transaction: FC<TransactionProps> = ({ header, state: txState, ...props })
 | 
			
		||||
    }
 | 
			
		||||
    setState({ txIsLoading: false })
 | 
			
		||||
  }, [
 | 
			
		||||
    txState.selectedTransaction?.value,
 | 
			
		||||
    viewType,
 | 
			
		||||
    accounts,
 | 
			
		||||
    txIsDisabled,
 | 
			
		||||
    setState,
 | 
			
		||||
    header,
 | 
			
		||||
    saveEditorState,
 | 
			
		||||
    editorValue,
 | 
			
		||||
    txState,
 | 
			
		||||
    selectedAccount?.value,
 | 
			
		||||
    prepareOptions
 | 
			
		||||
  ])
 | 
			
		||||
 | 
			
		||||
  const getJsonString = useCallback(
 | 
			
		||||
    (state?: Partial<TransactionState>) =>
 | 
			
		||||
      JSON.stringify(prepareOptions?.(state) || {}, null, editorSettings.tabSize),
 | 
			
		||||
    [editorSettings.tabSize, prepareOptions]
 | 
			
		||||
  )
 | 
			
		||||
 | 
			
		||||
  const resetState = useCallback(
 | 
			
		||||
    (transactionType: SelectOption | undefined = defaultTransactionType) => {
 | 
			
		||||
      const fields = getTxFields(transactionType?.value)
 | 
			
		||||
@@ -201,11 +210,21 @@ const Transaction: FC<TransactionProps> = ({ header, state: txState, ...props })
 | 
			
		||||
    [accounts, prepareOptions, setState, txState]
 | 
			
		||||
  )
 | 
			
		||||
 | 
			
		||||
  const switchToJson = useCallback(() => {
 | 
			
		||||
    const editorValue = getJsonString()
 | 
			
		||||
    setState({ viewType: 'json', editorValue })
 | 
			
		||||
  }, [getJsonString, setState])
 | 
			
		||||
 | 
			
		||||
  const switchToUI = useCallback(() => {
 | 
			
		||||
    setState({ viewType: 'ui' })
 | 
			
		||||
  }, [setState])
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <Box css={{ position: 'relative', height: 'calc(100% - 28px)' }} {...props}>
 | 
			
		||||
      {viewType === 'json' ? (
 | 
			
		||||
        <TxJson
 | 
			
		||||
          getJsonString={getJsonString}
 | 
			
		||||
          saveEditorState={saveEditorState}
 | 
			
		||||
          header={header}
 | 
			
		||||
          state={txState}
 | 
			
		||||
          setState={setState}
 | 
			
		||||
@@ -213,6 +232,7 @@ const Transaction: FC<TransactionProps> = ({ header, state: txState, ...props })
 | 
			
		||||
        />
 | 
			
		||||
      ) : (
 | 
			
		||||
        <TxUI
 | 
			
		||||
          switchToJson={switchToJson}
 | 
			
		||||
          state={txState}
 | 
			
		||||
          resetState={resetState}
 | 
			
		||||
          setState={setState}
 | 
			
		||||
@@ -233,8 +253,8 @@ const Transaction: FC<TransactionProps> = ({ header, state: txState, ...props })
 | 
			
		||||
        <Button
 | 
			
		||||
          onClick={() => {
 | 
			
		||||
            if (viewType === 'ui') {
 | 
			
		||||
              setState({ viewType: 'json' })
 | 
			
		||||
            } else setState({ viewType: 'ui' })
 | 
			
		||||
              switchToJson()
 | 
			
		||||
            } else switchToUI()
 | 
			
		||||
          }}
 | 
			
		||||
          outline
 | 
			
		||||
        >
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
import { FC, useCallback, useEffect, useMemo, useState } from 'react'
 | 
			
		||||
import { FC, useCallback, useEffect, useState } from 'react'
 | 
			
		||||
import { useSnapshot } from 'valtio'
 | 
			
		||||
import state, { prepareState, transactionsData, TransactionState } from '../../state'
 | 
			
		||||
import state, { transactionsData, TransactionState } from '../../state'
 | 
			
		||||
import Text from '../Text'
 | 
			
		||||
import { Flex, Link } from '..'
 | 
			
		||||
import { showAlert } from '../../state/actions/showAlert'
 | 
			
		||||
@@ -11,27 +11,27 @@ import Monaco from '../Monaco'
 | 
			
		||||
import type monaco from 'monaco-editor'
 | 
			
		||||
 | 
			
		||||
interface JsonProps {
 | 
			
		||||
  getJsonString?: (state?: Partial<TransactionState>) => string
 | 
			
		||||
  getJsonString: (st?: Partial<TransactionState>) => string
 | 
			
		||||
  saveEditorState: (val?: string, tt?: string) => TransactionState | undefined
 | 
			
		||||
  header?: string
 | 
			
		||||
  setState: (pTx?: Partial<TransactionState> | undefined) => void
 | 
			
		||||
  state: TransactionState
 | 
			
		||||
  estimateFee?: () => Promise<string | undefined>
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const TxJson: FC<JsonProps> = ({ getJsonString, state: txState, header, setState }) => {
 | 
			
		||||
export const TxJson: FC<JsonProps> = ({
 | 
			
		||||
  getJsonString,
 | 
			
		||||
  state: txState,
 | 
			
		||||
  header,
 | 
			
		||||
  setState,
 | 
			
		||||
  saveEditorState
 | 
			
		||||
}) => {
 | 
			
		||||
  const { editorSettings, accounts } = useSnapshot(state)
 | 
			
		||||
  const { editorValue, estimatedFee } = txState
 | 
			
		||||
  const { editorValue, estimatedFee, editorIsSaved } = txState
 | 
			
		||||
  const [currTxType, setCurrTxType] = useState<string | undefined>(
 | 
			
		||||
    txState.selectedTransaction?.value
 | 
			
		||||
  )
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    setState({
 | 
			
		||||
      editorValue: getJsonString?.()
 | 
			
		||||
    })
 | 
			
		||||
    // eslint-disable-next-line react-hooks/exhaustive-deps
 | 
			
		||||
  }, [])
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    const parsed = parseJSON(editorValue)
 | 
			
		||||
    if (!parsed) return
 | 
			
		||||
@@ -44,29 +44,19 @@ export const TxJson: FC<JsonProps> = ({ getJsonString, state: txState, header, s
 | 
			
		||||
    }
 | 
			
		||||
  }, [editorValue])
 | 
			
		||||
 | 
			
		||||
  const saveState = (value: string, transactionType?: string) => {
 | 
			
		||||
    const tx = prepareState(value, transactionType)
 | 
			
		||||
    if (tx) {
 | 
			
		||||
      setState(tx)
 | 
			
		||||
      setState({
 | 
			
		||||
        editorValue: getJsonString?.(tx)
 | 
			
		||||
      })
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const discardChanges = () => {
 | 
			
		||||
    showAlert('Confirm', {
 | 
			
		||||
      body: 'Are you sure to discard these changes?',
 | 
			
		||||
      confirmText: 'Yes',
 | 
			
		||||
      onCancel: () => {},
 | 
			
		||||
      onConfirm: () => setState({ editorValue: getJsonString?.() })
 | 
			
		||||
      onConfirm: () => setState({ editorValue: getJsonString() })
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const onExit = (value: string) => {
 | 
			
		||||
    const options = parseJSON(value)
 | 
			
		||||
    if (options) {
 | 
			
		||||
      saveState(value, currTxType)
 | 
			
		||||
      saveEditorState(value, currTxType)
 | 
			
		||||
      return
 | 
			
		||||
    }
 | 
			
		||||
    showAlert('Error!', {
 | 
			
		||||
@@ -163,8 +153,6 @@ export const TxJson: FC<JsonProps> = ({ getJsonString, state: txState, header, s
 | 
			
		||||
    })
 | 
			
		||||
  }, [getSchemas, monacoInst])
 | 
			
		||||
 | 
			
		||||
  const hasUnsaved = useMemo(() => editorValue !== getJsonString?.(), [editorValue, getJsonString])
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <Monaco
 | 
			
		||||
      rootProps={{
 | 
			
		||||
@@ -174,7 +162,7 @@ export const TxJson: FC<JsonProps> = ({ getJsonString, state: txState, header, s
 | 
			
		||||
      id={header}
 | 
			
		||||
      height="100%"
 | 
			
		||||
      value={editorValue}
 | 
			
		||||
      onChange={val => setState({ editorValue: val })}
 | 
			
		||||
      onChange={val => setState({ editorValue: val, editorIsSaved: false })}
 | 
			
		||||
      onMount={(editor, monaco) => {
 | 
			
		||||
        editor.updateOptions({
 | 
			
		||||
          minimap: { enabled: false },
 | 
			
		||||
@@ -190,12 +178,12 @@ export const TxJson: FC<JsonProps> = ({ getJsonString, state: txState, header, s
 | 
			
		||||
        model?.onWillDispose(() => onExit(model.getValue()))
 | 
			
		||||
      }}
 | 
			
		||||
      overlay={
 | 
			
		||||
        hasUnsaved ? (
 | 
			
		||||
        !editorIsSaved ? (
 | 
			
		||||
          <Flex row align="center" css={{ fontSize: '$xs', color: '$textMuted', ml: 'auto' }}>
 | 
			
		||||
            <Text muted small>
 | 
			
		||||
              This file has unsaved changes.
 | 
			
		||||
            </Text>
 | 
			
		||||
            <Link css={{ ml: '$1' }} onClick={() => saveState(editorValue || '', currTxType)}>
 | 
			
		||||
            <Link css={{ ml: '$1' }} onClick={() => saveEditorState(editorValue, currTxType)}>
 | 
			
		||||
              save
 | 
			
		||||
            </Link>
 | 
			
		||||
            <Link css={{ ml: '$1' }} onClick={discardChanges}>
 | 
			
		||||
 
 | 
			
		||||
@@ -25,9 +25,16 @@ interface UIProps {
 | 
			
		||||
  resetState: (tt?: SelectOption) => TransactionState | undefined
 | 
			
		||||
  state: TransactionState
 | 
			
		||||
  estimateFee?: (...arg: any) => Promise<string | undefined>
 | 
			
		||||
  switchToJson: () => void
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const TxUI: FC<UIProps> = ({ state: txState, setState, resetState, estimateFee }) => {
 | 
			
		||||
export const TxUI: FC<UIProps> = ({
 | 
			
		||||
  state: txState,
 | 
			
		||||
  setState,
 | 
			
		||||
  resetState,
 | 
			
		||||
  estimateFee,
 | 
			
		||||
  switchToJson
 | 
			
		||||
}) => {
 | 
			
		||||
  const { accounts } = useSnapshot(state)
 | 
			
		||||
  const {
 | 
			
		||||
    selectedAccount,
 | 
			
		||||
@@ -102,8 +109,6 @@ export const TxUI: FC<UIProps> = ({ state: txState, setState, resetState, estima
 | 
			
		||||
    [handleEstimateFee, resetState, setState]
 | 
			
		||||
  )
 | 
			
		||||
 | 
			
		||||
  const switchToJson = () => setState({ viewType: 'json' })
 | 
			
		||||
 | 
			
		||||
  // default tx
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    if (selectedTransaction?.value) return
 | 
			
		||||
 
 | 
			
		||||
@@ -36,6 +36,7 @@ export interface TransactionState {
 | 
			
		||||
  txFields: TxFields
 | 
			
		||||
  viewType: 'json' | 'ui'
 | 
			
		||||
  editorValue?: string
 | 
			
		||||
  editorIsSaved: boolean
 | 
			
		||||
  estimatedFee?: string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -53,6 +54,7 @@ export const defaultTransaction: TransactionState = {
 | 
			
		||||
  selectedFlags: null,
 | 
			
		||||
  hookParameters: {},
 | 
			
		||||
  memos: {},
 | 
			
		||||
  editorIsSaved: true,
 | 
			
		||||
  txIsLoading: false,
 | 
			
		||||
  txIsDisabled: false,
 | 
			
		||||
  txFields: {},
 | 
			
		||||
@@ -271,6 +273,7 @@ export const prepareState = (value: string, transactionType?: string) => {
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  tx.txFields = rest
 | 
			
		||||
  tx.editorIsSaved = true;
 | 
			
		||||
 | 
			
		||||
  return tx
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user