From 7e57a6815427d6a6690fa52c2fc776f4bf89eec7 Mon Sep 17 00:00:00 2001 From: Sagar Shah Date: Wed, 19 Jul 2023 18:46:48 -0500 Subject: [PATCH 1/2] wip --- .../cactiComponents/ActionResponse.tsx | 10 ++- src/components/experimental_/MessageList_.tsx | 39 ++++++++-- .../experimental_/MessageTranslator_.tsx | 2 +- .../MultiStepProgressIndicator.tsx | 34 +++++++++ .../containers/MultiStepContainer.tsx | 72 +++++++++++++------ .../widgets/helpers/WidgetError.tsx | 6 +- 6 files changed, 133 insertions(+), 30 deletions(-) create mode 100644 src/components/experimental_/MultiStepProgressIndicator.tsx diff --git a/src/components/cactiComponents/ActionResponse.tsx b/src/components/cactiComponents/ActionResponse.tsx index 8405dd3a3..12fb9f0e9 100644 --- a/src/components/cactiComponents/ActionResponse.tsx +++ b/src/components/cactiComponents/ActionResponse.tsx @@ -1,5 +1,6 @@ import { useEffect, useState } from 'react'; import Skeleton from 'react-loading-skeleton'; +import { TransactionReceipt } from '@ethersproject/abstract-provider'; import { AddressZero } from '@ethersproject/constants'; import { CheckCircleIcon, ExclamationTriangleIcon } from '@heroicons/react/24/outline'; import { ConnectButton } from '@rainbow-me/rainbowkit'; @@ -55,7 +56,8 @@ export type ActionResponseProps = { label?: string; disabled?: boolean; stepper?: boolean; - onSuccess?: () => JSX.Element | string; + onSuccess?: (txReceipt?: TransactionReceipt) => any; + onError?: (txHash?: string) => any; // assertCallParams?: AssertCallBasicParams; // altAction?: () => Promise; }; @@ -71,11 +73,13 @@ export const ActionResponse = ({ label: label_, disabled, stepper, + onSuccess, + onError, }: ActionResponseProps) => { const defaultLabel = label_ || 'Submit'; const { address } = useAccount(); - const { submitTx, isWaitingOnUser, isTransacting, error, isSuccess, receipt } = useSubmitTx( + const { submitTx, isWaitingOnUser, isTransacting, error, isSuccess, receipt, hash } = useSubmitTx( txParams, sendParams ); @@ -178,6 +182,7 @@ export const ActionResponse = ({ console.log('Error Building/Validating tx'); setLabel(`Error validating the transaction.`); setState(ActionResponseState.ERROR); + onError?.(hash); } /* case tx/approval success, waiting for tx-building */ @@ -210,6 +215,7 @@ export const ActionResponse = ({ console.log('TX SUCCESS'); setLabel('Transaction Complete'); setState(ActionResponseState.SUCCESS); + onSuccess?.(receipt); } } }, [ diff --git a/src/components/experimental_/MessageList_.tsx b/src/components/experimental_/MessageList_.tsx index 8bb3e85f7..c22574903 100644 --- a/src/components/experimental_/MessageList_.tsx +++ b/src/components/experimental_/MessageList_.tsx @@ -1,7 +1,9 @@ import React, { useEffect, useRef } from 'react'; +import { is } from 'date-fns/locale'; import { useChatContext } from '@/contexts/ChatContext'; import { BotThinking } from './BotThinking'; import { MessageItem } from './MessageItem_'; +import { MultiStepProgressIndicator } from './MultiStepProgressIndicator'; export const MessageList = () => { const { @@ -38,8 +40,11 @@ export const MessageList = () => { {message.messageId == insertBeforeMessageId && ( <> {bottomRefDiv} - {multiStepInProgress} - {isBotThinking ? : null} + )} @@ -49,11 +54,37 @@ export const MessageList = () => { {!insertBeforeMessageId && ( <> - {multiStepInProgress} - {isBotThinking ? : null} + {bottomRefDiv} )} ); }; + +const ProgressIndicators = ({ + isBotThinking, + isMultiStepInProgress, + bottomRef, +}: { + isBotThinking: boolean; + isMultiStepInProgress: boolean; + bottomRef: React.RefObject; +}) => { + useEffect(() => { + if (isMultiStepInProgress) { + bottomRef.current?.scrollIntoView({ behavior: 'smooth' }); + } + }, [isMultiStepInProgress, bottomRef]); + + return ( + <> + {isMultiStepInProgress ? : null} + {isBotThinking ? : null} + + ); +}; diff --git a/src/components/experimental_/MessageTranslator_.tsx b/src/components/experimental_/MessageTranslator_.tsx index ec723ae4b..a02ef6a1c 100644 --- a/src/components/experimental_/MessageTranslator_.tsx +++ b/src/components/experimental_/MessageTranslator_.tsx @@ -8,9 +8,9 @@ import { Widgetize } from '../MessageTranslator'; import { TextResponse } from '../cactiComponents'; import { ImageVariant } from '../cactiComponents/ImageResponse'; import { TableResponse } from '../cactiComponents/TableResponse'; -import { MultiStepContainer } from '../widgets/MultiStepContainer'; import { FeedbackButton } from './FeedbackButton_'; import ListContainer from './containers/ListContainer'; +import { MultiStepContainer } from './containers/MultiStepContainer'; import { StreamingContainer } from './containers/StreamingContainer'; import LiquityBorrow from './widgets/liquity/borrow/LiquityBorrow'; import LiquityClose from './widgets/liquity/close/LiquityClose'; diff --git a/src/components/experimental_/MultiStepProgressIndicator.tsx b/src/components/experimental_/MultiStepProgressIndicator.tsx new file mode 100644 index 000000000..3e5e9c713 --- /dev/null +++ b/src/components/experimental_/MultiStepProgressIndicator.tsx @@ -0,0 +1,34 @@ +import { Spinner } from '../../utils'; +import Avatar from '../Avatar'; +import { ResponseWrap } from '../cactiComponents/helpers/layout'; + +export const MultiStepProgressIndicator = () => { + return ( +
+
+
+ +
+
+ +
+ +
+ +
+ There are more steps in the current workflow, please wait as the system computes the + next step. +
+
+
+
+
+ ); +}; diff --git a/src/components/experimental_/containers/MultiStepContainer.tsx b/src/components/experimental_/containers/MultiStepContainer.tsx index b935fe8f2..c704452bf 100644 --- a/src/components/experimental_/containers/MultiStepContainer.tsx +++ b/src/components/experimental_/containers/MultiStepContainer.tsx @@ -1,7 +1,11 @@ import { useCallback, useEffect, useState } from 'react'; +import { TransactionReceipt } from '@ethersproject/abstract-provider'; +import { UnsignedTransaction } from 'ethers'; import { SendTransaction } from '@/components/widgets/SendTransaction'; import { useChatContext } from '@/contexts/ChatContext'; +import { ActionResponse, HeaderResponse } from '../../cactiComponents'; import { WidgetError } from '../widgets/helpers'; +import { ConnectFirst } from '../widgets/helpers/ConnectFirst'; interface MultiStepContainerProps { status: 'success' | 'error'; @@ -18,6 +22,8 @@ interface MultiStepContainerProps { } interface UserActionTxTypeProps { + stepNumber: number; + isFinalStep: boolean; tx: { from: string; to: string; value: string; data: string; gas: string } | null; sendStepResult: (stepStatus: string, stepStatusMessage: string, userActionData: string) => void; description: string; @@ -85,34 +91,60 @@ export const MultiStepContainer = ({ } if (userActionType === 'tx') { - return ; + return ( + + ); } if (userActionType === 'acknowledge') { - return
ACKNOWLEDGE WIDGET
; + return
ACKNOWLEDGEMENT ACTION TYPE NOT IMPLEMENTED
; } return
INVALID
; }; -export const UserActionTxType = ({ tx, sendStepResult, description }: UserActionTxTypeProps) => { - const handleTxResult = ( - sendError: Error | null, - txError: Error | null, - isTxSuccess: boolean, - sendTxData: any - ) => { - if (sendError?.message || txError?.message) { - const errMsg = sendError?.message || txError?.message; - sendStepResult('error', `Transaction failed, error: ${errMsg}`, sendTxData?.hash); - } else if (isTxSuccess && sendTxData?.hash) { - sendStepResult( - 'success', - `Transaction successful, hash: ${sendTxData?.hash}`, - sendTxData?.hash - ); - } +export const UserActionTxType = ({ + stepNumber, + isFinalStep, + tx, + sendStepResult, + description, +}: UserActionTxTypeProps) => { + const handleSuccess = (receipt?: TransactionReceipt) => { + sendStepResult('success', `Transaction successful`, receipt?.transactionHash || ''); + }; + + const handleError = (txHash?: string) => { + sendStepResult('error', `Transaction failed`, txHash || ''); }; - return ; + const unsignedTx: UnsignedTransaction = { + to: tx?.to, + data: tx?.data, + value: tx?.value, + gasLimit: tx?.gas, + }; + + const stepDescription = + stepNumber === 1 && isFinalStep ? description : `Step ${stepNumber}: ${description}`; + + return ( + + + + + ); }; diff --git a/src/components/experimental_/widgets/helpers/WidgetError.tsx b/src/components/experimental_/widgets/helpers/WidgetError.tsx index 3415f7455..1dcd04191 100644 --- a/src/components/experimental_/widgets/helpers/WidgetError.tsx +++ b/src/components/experimental_/widgets/helpers/WidgetError.tsx @@ -3,13 +3,13 @@ import { XCircleIcon } from '@heroicons/react/20/solid'; export const WidgetError = ({ children }: { children: ReactNode }) => { return ( -
+
-
-

{children}

+

Error: {children}

    From 98f3094dba4379a0a60c113ff3f1b1ddb256cd1b Mon Sep 17 00:00:00 2001 From: Sagar Shah Date: Thu, 20 Jul 2023 11:06:09 -0500 Subject: [PATCH 2/2] wip --- .../experimental_/MessageTranslator_.tsx | 5 +++ .../containers/SingleStepContainer.tsx | 43 +++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 src/components/experimental_/containers/SingleStepContainer.tsx diff --git a/src/components/experimental_/MessageTranslator_.tsx b/src/components/experimental_/MessageTranslator_.tsx index a02ef6a1c..07de5fdcb 100644 --- a/src/components/experimental_/MessageTranslator_.tsx +++ b/src/components/experimental_/MessageTranslator_.tsx @@ -11,6 +11,7 @@ import { TableResponse } from '../cactiComponents/TableResponse'; import { FeedbackButton } from './FeedbackButton_'; import ListContainer from './containers/ListContainer'; import { MultiStepContainer } from './containers/MultiStepContainer'; +import { SingleStepContainer } from './containers/SingleStepContainer'; import { StreamingContainer } from './containers/StreamingContainer'; import LiquityBorrow from './widgets/liquity/borrow/LiquityBorrow'; import LiquityClose from './widgets/liquity/close/LiquityClose'; @@ -82,6 +83,10 @@ export const MessageTranslator = ({ message }: { message: Message }) => { if (item.name === 'display-multistep-payload-container') return [...list, ]; + /* handle if a single step container is passed */ + if (item.name === 'display-tx-payload-for-sending-container') + return [...list, ]; + /* if item has a function name, assume its a widget */ return [...list, ]; } diff --git a/src/components/experimental_/containers/SingleStepContainer.tsx b/src/components/experimental_/containers/SingleStepContainer.tsx new file mode 100644 index 000000000..5a5bdce8a --- /dev/null +++ b/src/components/experimental_/containers/SingleStepContainer.tsx @@ -0,0 +1,43 @@ +import { UnsignedTransaction } from 'ethers'; +import { ActionResponse, HeaderResponse } from '../../cactiComponents'; +import { WidgetError } from '../widgets/helpers'; +import { ConnectFirst } from '../widgets/helpers/ConnectFirst'; + +// NOTE: May need to deprecate this in favor of MultiStepContainer +interface SingleStepContainerProps { + userRequestStatus: 'success' | 'error'; + tx: { from: string; to: string; value: string; data: string; gas: string } | null; + errorMsg: string; + parsedUserRequest: string; + description: string; +} + +export const SingleStepContainer = ({ + userRequestStatus, + tx, + errorMsg, + description, +}: SingleStepContainerProps) => { + if (userRequestStatus === 'error') { + return {errorMsg}; + } + + const unsignedTx: UnsignedTransaction = { + to: tx?.to, + data: tx?.data, + value: tx?.value, + gasLimit: tx?.gas, + }; + + return ( + + + + + ); +};