chore(1987): persist ui behind dialog when staking (#1997)

* Chore/1987: Persist UI behind dialog when staking

* feat(1987): Placed staking form tx status notifications in separate component
This commit is contained in:
Sam Keen 2022-11-10 11:31:11 +00:00 committed by GitHub
parent 4fedd94243
commit 7f8185372d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 147 additions and 46 deletions

View File

@ -206,7 +206,7 @@
"noGovernanceTokens": "You need some VEGA tokens to participate in governance", "noGovernanceTokens": "You need some VEGA tokens to participate in governance",
"youVoted": "You voted", "youVoted": "You voted",
"changeVote": "Change vote", "changeVote": "Change vote",
"voteRequested": "Please confirm transaction in wallet", "txRequested": "Confirm transaction in wallet",
"votePending": "Casting vote", "votePending": "Casting vote",
"voteError": "Something went wrong, and your vote was not seen by the network", "voteError": "Something went wrong, and your vote was not seen by the network",
"back": "back", "back": "back",

View File

@ -10,7 +10,7 @@ interface VoteTransactionDialogProps {
const dialogTitle = (voteState: VoteState): string | undefined => { const dialogTitle = (voteState: VoteState): string | undefined => {
switch (voteState) { switch (voteState) {
case VoteState.Requested: case VoteState.Requested:
return t('voteRequested'); return t('txRequested');
case VoteState.Pending: case VoteState.Pending:
return t('votePending'); return t('votePending');
default: default:

View File

@ -3,15 +3,22 @@ import { useTranslation } from 'react-i18next';
interface StakeFailureProps { interface StakeFailureProps {
nodeName: string; nodeName: string;
isDialogVisible: boolean;
toggleDialog: () => void;
} }
export const StakeFailure = ({ nodeName }: StakeFailureProps) => { export const StakeFailure = ({
nodeName,
isDialogVisible,
toggleDialog,
}: StakeFailureProps) => {
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
<Dialog <Dialog
intent={Intent.Danger} intent={Intent.Danger}
title={t('Something went wrong')} title={t('Something went wrong')}
open={true} open={isDialogVisible}
onChange={toggleDialog}
> >
<p> <p>
{t('stakeFailed', { {t('stakeFailed', {

View File

@ -7,12 +7,16 @@ interface StakePendingProps {
action: StakeAction; action: StakeAction;
amount: string; amount: string;
nodeName: string; nodeName: string;
isDialogVisible: boolean;
toggleDialog: () => void;
} }
export const StakePending = ({ export const StakePending = ({
action, action,
amount, amount,
nodeName, nodeName,
isDialogVisible,
toggleDialog,
}: StakePendingProps) => { }: StakePendingProps) => {
const { t } = useTranslation(); const { t } = useTranslation();
const titleArgs = { amount, node: nodeName }; const titleArgs = { amount, node: nodeName };
@ -22,7 +26,12 @@ export const StakePending = ({
: t('stakeRemovePendingTitle', titleArgs); : t('stakeRemovePendingTitle', titleArgs);
return ( return (
<Dialog icon={<Loader size="small" />} title={title} open={true}> <Dialog
icon={<Loader size="small" />}
title={title}
open={isDialogVisible}
onChange={toggleDialog}
>
<p>{t('timeForConfirmation')}</p> <p>{t('timeForConfirmation')}</p>
</Dialog> </Dialog>
); );

View File

@ -0,0 +1,25 @@
import { Dialog, Intent } from '@vegaprotocol/ui-toolkit';
import { useTranslation } from 'react-i18next';
import React from 'react';
interface StakeRequestedProps {
isDialogVisible: boolean;
toggleDialog: () => void;
}
export const StakeRequested = ({
isDialogVisible,
toggleDialog,
}: StakeRequestedProps) => {
const { t } = useTranslation();
return (
<Dialog
title={t('txRequested')}
intent={Intent.Warning}
open={isDialogVisible}
onChange={toggleDialog}
>
<p>{t('stakingConfirm')}</p>
</Dialog>
);
};

View File

@ -10,6 +10,8 @@ interface StakeSuccessProps {
amount: string; amount: string;
nodeName: string; nodeName: string;
removeType: RemoveType; removeType: RemoveType;
isDialogVisible: boolean;
toggleDialog: () => void;
} }
export const StakeSuccess = ({ export const StakeSuccess = ({
@ -17,6 +19,8 @@ export const StakeSuccess = ({
amount, amount,
nodeName, nodeName,
removeType, removeType,
isDialogVisible,
toggleDialog,
}: StakeSuccessProps) => { }: StakeSuccessProps) => {
const { t } = useTranslation(); const { t } = useTranslation();
const isAdd = action === Actions.Add; const isAdd = action === Actions.Add;
@ -34,7 +38,8 @@ export const StakeSuccess = ({
icon={<Icon name="tick" />} icon={<Icon name="tick" />}
intent={Intent.Success} intent={Intent.Success}
title={title} title={title}
open={true} open={isDialogVisible}
onChange={toggleDialog}
> >
<div> <div>
<p>{message}</p> <p>{message}</p>

View File

@ -0,0 +1,67 @@
import { StakeFailure } from './stake-failure';
import { StakeRequested } from './stake-requested';
import { StakePending } from './stake-pending';
import { StakeSuccess } from './stake-success';
import { FormState } from './staking-form';
import type { RemoveType, StakeAction } from './staking-form';
interface StakeFormTxStatusesProps {
formState: FormState;
nodeName: string;
amount: string;
action: StakeAction;
removeType: RemoveType;
isDialogVisible: boolean;
toggleDialog: () => void;
}
export const StakingFormTxStatuses = ({
formState,
nodeName,
amount,
action,
removeType,
isDialogVisible,
toggleDialog,
}: StakeFormTxStatusesProps) => {
switch (formState) {
case FormState.Requested:
return (
<StakeRequested
isDialogVisible={isDialogVisible}
toggleDialog={toggleDialog}
/>
);
case FormState.Pending:
return (
<StakePending
action={action}
amount={amount}
nodeName={nodeName}
isDialogVisible={isDialogVisible}
toggleDialog={toggleDialog}
/>
);
case FormState.Success:
return (
<StakeSuccess
action={action}
amount={amount}
nodeName={nodeName}
isDialogVisible={isDialogVisible}
toggleDialog={toggleDialog}
removeType={removeType}
/>
);
case FormState.Failure:
return (
<StakeFailure
nodeName={nodeName}
isDialogVisible={isDialogVisible}
toggleDialog={toggleDialog}
/>
);
default:
return null;
}
};

View File

@ -1,6 +1,6 @@
import { gql, useApolloClient } from '@apollo/client'; import { gql, useApolloClient } from '@apollo/client';
import * as Sentry from '@sentry/react'; import * as Sentry from '@sentry/react';
import React from 'react'; import React, { useCallback, useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
@ -12,14 +12,10 @@ import type {
PartyDelegations, PartyDelegations,
PartyDelegationsVariables, PartyDelegationsVariables,
} from './__generated__/PartyDelegations'; } from './__generated__/PartyDelegations';
import { StakeFailure } from './stake-failure'; import { StakingFormTxStatuses } from './staking-form-tx-statuses';
import { StakePending } from './stake-pending';
import { StakeSuccess } from './stake-success';
import { import {
ButtonLink, ButtonLink,
Dialog,
FormGroup, FormGroup,
Intent,
Radio, Radio,
RadioGroup, RadioGroup,
} from '@vegaprotocol/ui-toolkit'; } from '@vegaprotocol/ui-toolkit';
@ -54,7 +50,7 @@ export const PARTY_DELEGATIONS_QUERY = gql`
} }
`; `;
enum FormState { export enum FormState {
Default, Default,
Requested, Requested,
Pending, Pending,
@ -93,6 +89,7 @@ export const StakingForm = ({
const { appState } = useAppState(); const { appState } = useAppState();
const { sendTx } = useVegaWallet(); const { sendTx } = useVegaWallet();
const [formState, setFormState] = React.useState(FormState.Default); const [formState, setFormState] = React.useState(FormState.Default);
const [isDialogVisible, setIsDialogVisible] = useState(false);
const { t } = useTranslation(); const { t } = useTranslation();
const [action, setAction] = React.useState<StakeAction>( const [action, setAction] = React.useState<StakeAction>(
params.action as StakeAction params.action as StakeAction
@ -129,6 +126,7 @@ export const StakingForm = ({
async function onSubmit() { async function onSubmit() {
setFormState(FormState.Requested); setFormState(FormState.Requested);
setIsDialogVisible(true);
const delegateInput: DelegateSubmissionBody = { const delegateInput: DelegateSubmissionBody = {
delegateSubmission: { delegateSubmission: {
nodeId, nodeId,
@ -196,43 +194,24 @@ export const StakingForm = ({
return () => clearInterval(interval); return () => clearInterval(interval);
}, [formState, client, pubKey, nodeId]); }, [formState, client, pubKey, nodeId]);
if (formState === FormState.Failure) { const toggleDialog = useCallback(() => {
return <StakeFailure nodeName={nodeName} />; setIsDialogVisible(!isDialogVisible);
} else if (formState === FormState.Requested) { }, [isDialogVisible]);
return (
<Dialog
title="Confirm transaction in wallet"
intent={Intent.Warning}
open={true}
>
<p>{t('stakingConfirm')}</p>
</Dialog>
);
} else if (formState === FormState.Pending) {
return <StakePending action={action} amount={amount} nodeName={nodeName} />;
} else if (formState === FormState.Success) {
return (
<StakeSuccess
action={action}
amount={amount}
nodeName={nodeName}
removeType={removeType}
/>
);
} else if (
availableStakeToAdd.isEqualTo(0) &&
availableStakeToRemove.isEqualTo(0)
) {
if (appState.lien.isGreaterThan(0)) {
return <span className="text-red">{t('stakeNodeWrongVegaKey')}</span>;
} else {
return <span className="text-red">{t('stakeNodeNone')}</span>;
}
}
return ( return (
<> <>
<h2>{t('Manage your stake')}</h2> <h2>{t('Manage your stake')}</h2>
{formState === FormState.Default &&
availableStakeToAdd.isEqualTo(0) &&
availableStakeToRemove.isEqualTo(0) && (
<div>
{appState.lien.isGreaterThan(0) ? (
<span className="text-red">{t('stakeNodeWrongVegaKey')}</span>
) : (
<span className="text-red">{t('stakeNodeNone')}</span>
)}
</div>
)}
<FormGroup <FormGroup
label={t('Select if you want to add or remove stake')} label={t('Select if you want to add or remove stake')}
labelFor="radio-stake-options" labelFor="radio-stake-options"
@ -331,6 +310,15 @@ export const StakingForm = ({
)} )}
</> </>
)} )}
<StakingFormTxStatuses
formState={formState}
nodeName={nodeName}
amount={amount}
action={action}
removeType={removeType}
isDialogVisible={isDialogVisible}
toggleDialog={toggleDialog}
/>
</> </>
); );
}; };