feat(2211): download proposal forms data as json (#2521)

* feat(2211): view proposal forms data as json

* feat(2211): removed the vega wallet barrier to viewing proposal forms

* feat(2211): tweaked the json viewing to download the proposal form json, with a useful title (proposal title and readable datetime)

* feat(2211): removed unwanted NX_SENTRY_DSN config from dev environments

* feat(2211): unit test for download-json.ts

* feat(2211): unit test for proposal-form-download-json.spec.tsx

* feat(2211): simplified unit test for proposal-form-download-json.spec.tsx

* feat(2211): removed unneeded unit test

* feat(2211): revoked change that was causing test failures
This commit is contained in:
Sam Keen 2023-01-09 09:48:47 +00:00 committed by GitHub
parent 863c288e0d
commit c5b72e5a64
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 978 additions and 766 deletions

View File

@ -6,4 +6,3 @@ NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
NX_VEGA_EXPLORER_URL=https://stagnet3.explorer.vega.xyz
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40:87edc2605e544f888305d7fc4a9141bd@o286262.ingest.sentry.io/5882996

View File

@ -9,4 +9,3 @@ NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40:87edc2605e544f888305d7fc4a9141bd@o286262.ingest.sentry.io/5882996

View File

@ -159,8 +159,10 @@
"Tokens are held in different <trancheLink>Tranches</trancheLink>. Each tranche has its own schedule for how the tokens are unlocked.": "Tokens are held in different <trancheLink>Tranches</trancheLink>. Each tranche has its own schedule for how the tokens are unlocked.",
"proposals": "Proposals",
"proposal": "Proposal",
"submitting": "Submitting",
"submittingProposal": "Submitting proposal",
"submit": "Submit",
"submitProposal": "Submit proposal",
"connectWalletToSubmitProposal": "Connect your wallet to submit a proposal",
"proposedEnactment": "Proposed enactment",
"Enacted": "Enacted",
"enactedOn": "Enacted on",
@ -729,5 +731,6 @@
"homeRewardsIntro": "Track rewards you've earned for trading, liquidity provision, market creation, and staking.",
"homeRewardsButtonText": "See rewards",
"homeVegaTokenIntro": "VEGA Token is a governance asset used to make and vote on proposals, and nominate validators.",
"homeVegaTokenButtonText": "Manage tokens"
"homeVegaTokenButtonText": "Manage tokens",
"downloadProposalJson": "Download proposal as JSON"
}

View File

@ -0,0 +1,26 @@
export const downloadJson = (jsonString: string, proposalTitle: string) => {
try {
const now = new Date();
const day = now.getDate().toString().padStart(2, '0');
const month = now.toLocaleString('en-US', { month: 'short' });
const year = now.getFullYear().toString();
const hours = now.getHours().toString().padStart(2, '0');
const minutes = now.getMinutes().toString().padStart(2, '0');
const seconds = now.getSeconds().toString().padStart(2, '0');
// e.g. "2023-Jan-03-23-59-59"
const formattedDateTime = `${day}-${month}-${year}-${hours}-${minutes}-${seconds}`;
const blob = new Blob([jsonString], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
a.download = `${proposalTitle}-${formattedDateTime}.json`;
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
document.body.removeChild(a);
} catch (error) {
console.log(error);
}
};

View File

@ -5,3 +5,4 @@ export * from './proposal-form-terms';
export * from './proposal-form-submit';
export * from './proposal-form-transaction-dialog';
export * from './proposal-form-vote-and-enactment-deadline';
export * from './proposal-form-download-json';

View File

@ -0,0 +1,12 @@
import { fireEvent, render, screen } from '@testing-library/react';
import { ProposalFormDownloadJson } from './proposal-form-download-json';
describe('ProposalFormDownloadJson', () => {
it('calls the downloadJson method when the button is clicked', () => {
const downloadJson = jest.fn();
render(<ProposalFormDownloadJson downloadJson={downloadJson} />);
const button = screen.getByTestId('proposal-download-json');
fireEvent.click(button);
expect(downloadJson).toHaveBeenCalledTimes(1);
});
});

View File

@ -0,0 +1,19 @@
import { useTranslation } from 'react-i18next';
import { Button } from '@vegaprotocol/ui-toolkit';
interface ProposalFormDownloadJsonProps {
downloadJson: () => void;
}
export const ProposalFormDownloadJson = ({
downloadJson,
}: ProposalFormDownloadJsonProps) => {
const { t } = useTranslation();
return (
<div className="mb-6">
<Button data-testid="proposal-download-json" onClick={downloadJson}>
{t('downloadProposalJson')}
</Button>
</div>
);
};

View File

@ -0,0 +1,59 @@
import { render, screen } from '@testing-library/react';
import { VegaWalletContext } from '@vegaprotocol/wallet';
import { AppStateProvider } from '../../../../contexts/app-state/app-state-provider';
import { ProposalFormSubmit } from './proposal-form-submit';
import type { VegaWalletContextShape } from '@vegaprotocol/wallet';
const renderComponent = (
context: VegaWalletContextShape,
isSubmitting: boolean
) => {
render(
<AppStateProvider>
<VegaWalletContext.Provider value={context}>
<ProposalFormSubmit isSubmitting={isSubmitting} />
</VegaWalletContext.Provider>
</AppStateProvider>
);
};
describe('Proposal Form Submit', () => {
it('should display connection message and button if wallet not connected', () => {
renderComponent({ pubKey: null } as VegaWalletContextShape, false);
expect(
screen.getByText('Connect your wallet to submit a proposal')
).toBeInTheDocument();
expect(
screen.getByTestId('connect-to-vega-wallet-btn')
).toBeInTheDocument();
});
it('should display submit button if wallet is connected', () => {
const pubKey = { publicKey: '123456__123456', name: 'test' };
renderComponent(
{
pubKey: pubKey.publicKey,
pubKeys: [pubKey],
} as VegaWalletContextShape,
false
);
expect(screen.getByTestId('proposal-submit')).toHaveTextContent(
'Submit proposal'
);
});
it('should display submitting button text if wallet is connected and submitting', () => {
const pubKey = { publicKey: '123456__123456', name: 'test' };
renderComponent(
{
pubKey: pubKey.publicKey,
pubKeys: [pubKey],
} as VegaWalletContextShape,
true
);
expect(screen.getByTestId('proposal-submit')).toHaveTextContent(
'Submitting proposal'
);
});
});

View File

@ -1,5 +1,7 @@
import { useTranslation } from 'react-i18next';
import { Button } from '@vegaprotocol/ui-toolkit';
import { useVegaWallet } from '@vegaprotocol/wallet';
import { VegaWalletContainer } from '../../../../components/vega-wallet-container';
interface ProposalFormSubmitProps {
isSubmitting: boolean;
@ -8,17 +10,25 @@ interface ProposalFormSubmitProps {
export const ProposalFormSubmit = ({
isSubmitting,
}: ProposalFormSubmitProps) => {
const { pubKey } = useVegaWallet();
const { t } = useTranslation();
return (
<div className="mt-10 my-20">
<div className="mb-6">
<div className="mb-4 font-bold uppercase text-vega-orange">
{!pubKey && t('connectWalletToSubmitProposal')}
</div>
<VegaWalletContainer>
{() => (
<Button
variant="primary"
type="submit"
data-testid="proposal-submit"
disabled={isSubmitting}
>
{isSubmitting ? t('Submitting') : t('Submit')} {t('Proposal')}
{isSubmitting ? t('submittingProposal') : t('submitProposal')}
</Button>
)}
</VegaWalletContainer>
</div>
);
};

View File

@ -437,7 +437,7 @@ export function ProposalFormVoteAndEnactmentDeadline({
const { t } = useTranslation();
return (
<>
<div className="mb-10">
<ProposalFormSubheader>
{enactmentRegister && enactmentMinClose && enactmentMaxClose
? t('ProposalVoteAndEnactmentTitle')
@ -535,6 +535,6 @@ export function ProposalFormVoteAndEnactmentDeadline({
maxEnactmentHours={maxEnactmentHours}
/>
)}
</>
</div>
);
}

View File

@ -109,6 +109,7 @@ describe('Propose Freeform', () => {
expect(screen.getByTestId('proposal-description')).toBeTruthy();
expect(screen.getByTestId('proposal-vote-deadline')).toBeTruthy();
expect(screen.getByTestId('proposal-submit')).toBeTruthy();
expect(screen.getByTestId('proposal-download-json')).toBeTruthy();
expect(screen.getByTestId('proposal-transaction-dialog')).toBeTruthy();
});
});

View File

@ -12,18 +12,19 @@ import {
ProposalFormSubmit,
ProposalFormTitle,
ProposalFormTransactionDialog,
ProposalFormDownloadJson,
ProposalFormVoteAndEnactmentDeadline,
} from '../../components/propose';
import { ProposalMinRequirements } from '../../components/shared';
import { AsyncRenderer, ExternalLink } from '@vegaprotocol/ui-toolkit';
import { Heading } from '../../../../components/heading';
import { VegaWalletContainer } from '../../../../components/vega-wallet-container';
import {
createDocsLinks,
NetworkParams,
useNetworkParams,
} from '@vegaprotocol/react-helpers';
import { ProposalUserAction } from '../../components/shared';
import { downloadJson } from '../../../../lib/download-json';
export interface FreeformProposalFormFields {
proposalVoteDeadline: string;
@ -50,10 +51,11 @@ export const ProposeFreeform = () => {
handleSubmit,
formState: { isSubmitting, errors },
setValue,
watch,
} = useForm<FreeformProposalFormFields>();
const { finalizedProposal, submit, Dialog } = useProposalSubmit();
const onSubmit = async (fields: FreeformProposalFormFields) => {
const assembleProposal = (fields: FreeformProposalFormFields) => {
const isVoteDeadlineAtMinimum =
fields.proposalVoteDeadline ===
deadlineToRoundedHours(
@ -66,7 +68,7 @@ export const ProposeFreeform = () => {
params.governance_proposal_freeform_maxClose
).toString();
await submit({
return {
rationale: {
title: fields.proposalTitle,
description: fields.proposalDescription,
@ -79,15 +81,30 @@ export const ProposeFreeform = () => {
isVoteDeadlineAtMaximum
),
},
});
};
};
const onSubmit = async (fields: FreeformProposalFormFields) => {
await submit(assembleProposal(fields));
};
const viewJson = () => {
const formData = watch();
downloadJson(
JSON.stringify(assembleProposal(formData)),
'vega-freeform-proposal'
);
};
return (
<AsyncRenderer loading={loading} error={error} data={params}>
<Heading title={t('NewFreeformProposal')} />
<VegaWalletContainer>
{() => (
<AsyncRenderer
loading={loading}
error={error}
data={params}
render={(params) => (
<>
<Heading title={t('NewFreeformProposal')} />
<ProposalMinRequirements
minProposalBalance={
params.governance_proposal_freeform_minProposerBalance
@ -150,6 +167,7 @@ export const ProposeFreeform = () => {
/>
<ProposalFormSubmit isSubmitting={isSubmitting} />
<ProposalFormDownloadJson downloadJson={viewJson} />
<ProposalFormTransactionDialog
finalizedProposal={finalizedProposal}
TransactionDialog={Dialog}
@ -158,7 +176,6 @@ export const ProposeFreeform = () => {
</div>
</>
)}
</VegaWalletContainer>
</AsyncRenderer>
/>
);
};

View File

@ -112,6 +112,7 @@ describe('Propose Network Parameter', () => {
expect(screen.getByTestId('proposal-vote-deadline')).toBeTruthy();
expect(screen.getByTestId('proposal-enactment-deadline')).toBeTruthy();
expect(screen.getByTestId('proposal-submit')).toBeTruthy();
expect(screen.getByTestId('proposal-download-json')).toBeTruthy();
expect(screen.getByTestId('proposal-transaction-dialog')).toBeTruthy();
});

View File

@ -20,6 +20,7 @@ import {
ProposalFormTitle,
ProposalFormTransactionDialog,
ProposalFormVoteAndEnactmentDeadline,
ProposalFormDownloadJson,
} from '../../components/propose';
import { ProposalMinRequirements } from '../../components/shared';
import {
@ -33,8 +34,8 @@ import {
TextArea,
} from '@vegaprotocol/ui-toolkit';
import { Heading } from '../../../../components/heading';
import { VegaWalletContainer } from '../../../../components/vega-wallet-container';
import { ProposalUserAction } from '../../components/shared';
import { downloadJson } from '../../../../lib/download-json';
interface SelectedNetworkParamCurrentValueProps {
value: string;
@ -92,6 +93,7 @@ export const ProposeNetworkParameter = () => {
handleSubmit,
formState: { isSubmitting, errors },
setValue,
watch,
} = useForm<NetworkParameterProposalFormFields>();
const { finalizedProposal, submit, Dialog } = useProposalSubmit();
@ -99,8 +101,8 @@ export const ProposeNetworkParameter = () => {
? Object.entries(params).find(([key]) => key === selectedNetworkParam)
: null;
const onSubmit = async (fields: NetworkParameterProposalFormFields) => {
const acutalNetworkParamKey = fields.proposalNetworkParameterKey
const assembleProposal = (fields: NetworkParameterProposalFormFields) => {
const actualNetworkParamKey = fields.proposalNetworkParameterKey
.split('_')
.join('.');
@ -121,7 +123,7 @@ export const ProposeNetworkParameter = () => {
params.governance_proposal_updateNetParam_maxEnact
);
await submit({
return {
rationale: {
title: fields.proposalTitle,
description: fields.proposalDescription,
@ -129,7 +131,7 @@ export const ProposeNetworkParameter = () => {
terms: {
updateNetworkParameter: {
changes: {
key: acutalNetworkParamKey,
key: actualNetworkParamKey,
value: fields.proposalNetworkParameterValue,
},
},
@ -144,7 +146,19 @@ export const ProposeNetworkParameter = () => {
isEnactmentDeadlineAtMaximum
),
},
});
};
};
const onSubmit = async (fields: NetworkParameterProposalFormFields) => {
await submit(assembleProposal(fields));
};
const viewJson = () => {
const formData = watch();
downloadJson(
JSON.stringify(assembleProposal(formData)),
'vega-network-param-proposal'
);
};
return (
@ -152,11 +166,9 @@ export const ProposeNetworkParameter = () => {
loading={networkParamsLoading}
error={networkParamsError}
data={params}
>
<Heading title={t('NetworkParameterProposal')} />
<VegaWalletContainer>
{() => (
render={(params) => (
<>
<Heading title={t('NetworkParameterProposal')} />
<ProposalMinRequirements
minProposalBalance={
params.governance_proposal_updateNetParam_minProposerBalance
@ -300,6 +312,7 @@ export const ProposeNetworkParameter = () => {
/>
<ProposalFormSubmit isSubmitting={isSubmitting} />
<ProposalFormDownloadJson downloadJson={viewJson} />
<ProposalFormTransactionDialog
finalizedProposal={finalizedProposal}
TransactionDialog={Dialog}
@ -308,7 +321,6 @@ export const ProposeNetworkParameter = () => {
</div>
</>
)}
</VegaWalletContainer>
</AsyncRenderer>
/>
);
};

View File

@ -110,6 +110,7 @@ describe('Propose New Asset', () => {
expect(screen.getByTestId('proposal-validation-deadline')).toBeTruthy();
expect(screen.getByTestId('proposal-enactment-deadline')).toBeTruthy();
expect(screen.getByTestId('proposal-submit')).toBeTruthy();
expect(screen.getByTestId('proposal-download-json')).toBeTruthy();
expect(screen.getByTestId('proposal-transaction-dialog')).toBeTruthy();
});
});

View File

@ -21,13 +21,14 @@ import {
ProposalFormTerms,
ProposalFormTitle,
ProposalFormTransactionDialog,
ProposalFormDownloadJson,
ProposalFormVoteAndEnactmentDeadline,
} from '../../components/propose';
import { ProposalMinRequirements } from '../../components/shared';
import { AsyncRenderer, ExternalLink } from '@vegaprotocol/ui-toolkit';
import { Heading } from '../../../../components/heading';
import { VegaWalletContainer } from '../../../../components/vega-wallet-container';
import { ProposalUserAction } from '../../components/shared';
import { downloadJson } from '../../../../lib/download-json';
export interface NewAssetProposalFormFields {
proposalVoteDeadline: string;
@ -62,10 +63,11 @@ export const ProposeNewAsset = () => {
handleSubmit,
formState: { isSubmitting, errors },
setValue,
watch,
} = useForm<NewAssetProposalFormFields>();
const { finalizedProposal, submit, Dialog } = useProposalSubmit();
const onSubmit = async (fields: NewAssetProposalFormFields) => {
const assembleProposal = (fields: NewAssetProposalFormFields) => {
const isVoteDeadlineAtMinimum = doesValueEquateToParam(
fields.proposalVoteDeadline,
params.governance_proposal_asset_minClose
@ -87,7 +89,7 @@ export const ProposeNewAsset = () => {
params.governance_proposal_asset_maxClose
);
await submit({
return {
rationale: {
title: fields.proposalTitle,
description: fields.proposalDescription,
@ -111,7 +113,19 @@ export const ProposeNewAsset = () => {
isValidationDeadlineAtMaximum
),
},
});
};
};
const onSubmit = async (fields: NewAssetProposalFormFields) => {
await submit(assembleProposal(fields));
};
const viewJson = () => {
const formData = watch();
downloadJson(
JSON.stringify(assembleProposal(formData)),
'vega-new-asset-proposal'
);
};
return (
@ -119,11 +133,10 @@ export const ProposeNewAsset = () => {
loading={networkParamsLoading}
error={networkParamsError}
data={params}
>
<Heading title={t('NewAssetProposal')} />
<VegaWalletContainer>
{() => (
render={(params) => (
<>
<Heading title={t('NewAssetProposal')} />
<ProposalMinRequirements
minProposalBalance={
params.governance_proposal_asset_minProposerBalance
@ -216,6 +229,7 @@ export const ProposeNewAsset = () => {
/>
<ProposalFormSubmit isSubmitting={isSubmitting} />
<ProposalFormDownloadJson downloadJson={viewJson} />
<ProposalFormTransactionDialog
finalizedProposal={finalizedProposal}
TransactionDialog={Dialog}
@ -224,7 +238,6 @@ export const ProposeNewAsset = () => {
</div>
</>
)}
</VegaWalletContainer>
</AsyncRenderer>
/>
);
};

View File

@ -104,6 +104,7 @@ describe('Propose New Market', () => {
expect(screen.getByTestId('proposal-vote-deadline')).toBeTruthy();
expect(screen.getByTestId('proposal-enactment-deadline')).toBeTruthy();
expect(screen.getByTestId('proposal-submit')).toBeTruthy();
expect(screen.getByTestId('proposal-download-json')).toBeTruthy();
expect(screen.getByTestId('proposal-transaction-dialog')).toBeTruthy();
});
});

View File

@ -20,13 +20,14 @@ import {
ProposalFormTerms,
ProposalFormTitle,
ProposalFormTransactionDialog,
ProposalFormDownloadJson,
ProposalFormVoteAndEnactmentDeadline,
} from '../../components/propose';
import { ProposalMinRequirements } from '../../components/shared';
import { AsyncRenderer, ExternalLink } from '@vegaprotocol/ui-toolkit';
import { Heading } from '../../../../components/heading';
import { VegaWalletContainer } from '../../../../components/vega-wallet-container';
import { ProposalUserAction } from '../../components/shared';
import { downloadJson } from '../../../../lib/download-json';
export interface NewMarketProposalFormFields {
proposalVoteDeadline: string;
@ -60,10 +61,11 @@ export const ProposeNewMarket = () => {
handleSubmit,
formState: { isSubmitting, errors },
setValue,
watch,
} = useForm<NewMarketProposalFormFields>();
const { finalizedProposal, submit, Dialog } = useProposalSubmit();
const onSubmit = async (fields: NewMarketProposalFormFields) => {
const assembleProposal = (fields: NewMarketProposalFormFields) => {
const isVoteDeadlineAtMinimum = doesValueEquateToParam(
fields.proposalVoteDeadline,
params.governance_proposal_market_minClose
@ -81,7 +83,7 @@ export const ProposeNewMarket = () => {
params.governance_proposal_market_maxEnact
);
await submit({
return {
rationale: {
title: fields.proposalTitle,
description: fields.proposalDescription,
@ -101,7 +103,19 @@ export const ProposeNewMarket = () => {
isEnactmentDeadlineAtMaximum
),
},
});
};
};
const onSubmit = async (fields: NewMarketProposalFormFields) => {
await submit(assembleProposal(fields));
};
const viewJson = () => {
const formData = watch();
downloadJson(
JSON.stringify(assembleProposal(formData)),
'vega-new-market-proposal'
);
};
return (
@ -109,11 +123,10 @@ export const ProposeNewMarket = () => {
loading={networkParamsLoading}
error={networkParamsError}
data={params}
>
<Heading title={t('NewMarketProposal')} />
<VegaWalletContainer>
{() => (
render={(params) => (
<>
<Heading title={t('NewMarketProposal')} />
<ProposalMinRequirements
minProposalBalance={
params.governance_proposal_market_minProposerBalance
@ -198,6 +211,7 @@ export const ProposeNewMarket = () => {
/>
<ProposalFormSubmit isSubmitting={isSubmitting} />
<ProposalFormDownloadJson downloadJson={viewJson} />
<ProposalFormTransactionDialog
finalizedProposal={finalizedProposal}
TransactionDialog={Dialog}
@ -206,7 +220,6 @@ export const ProposeNewMarket = () => {
</div>
</>
)}
</VegaWalletContainer>
</AsyncRenderer>
/>
);
};

View File

@ -2,7 +2,6 @@ import { useForm } from 'react-hook-form';
import { useTranslation } from 'react-i18next';
import { useEnvironment } from '@vegaprotocol/environment';
import { Heading } from '../../../../components/heading';
import { VegaWalletContainer } from '../../../../components/vega-wallet-container';
import {
AsyncRenderer,
ExternalLink,
@ -20,8 +19,10 @@ import { useProposalSubmit } from '@vegaprotocol/governance';
import {
ProposalFormSubmit,
ProposalFormTransactionDialog,
ProposalFormDownloadJson,
} from '../../components/propose';
import { ProposalRawMinRequirements } from './proposal-raw-min-requirements';
import { downloadJson } from '../../../../lib/download-json';
export interface RawProposalFormFields {
rawProposalData: string;
@ -48,6 +49,7 @@ export const ProposeRaw = () => {
register,
handleSubmit,
formState: { isSubmitting, errors },
watch,
} = useForm<RawProposalFormFields>();
const { finalizedProposal, submit, Dialog } = useProposalSubmit();
@ -57,16 +59,20 @@ export const ProposeRaw = () => {
await submit(JSON.parse(fields.rawProposalData));
};
const viewJson = () => {
const formData = watch();
downloadJson(JSON.stringify(formData), 'vega-raw-proposal');
};
return (
<AsyncRenderer
loading={networkParamsLoading}
error={networkParamsError}
data={params}
>
<Heading title={t('NewRawProposal')} />
<VegaWalletContainer>
{() => (
render={(params) => (
<>
<Heading title={t('NewRawProposal')} />
<ProposalRawMinRequirements
assetMin={params.governance_proposal_asset_minProposerBalance}
updateAssetMin={
@ -79,9 +85,7 @@ export const ProposeRaw = () => {
updateNetParamMin={
params.governance_proposal_updateNetParam_minProposerBalance
}
freeformMin={
params.governance_proposal_freeform_minProposerBalance
}
freeformMin={params.governance_proposal_freeform_minProposerBalance}
spamProtectionMin={params.spam_protection_proposal_min_tokens}
/>
@ -130,6 +134,7 @@ export const ProposeRaw = () => {
)}
</FormGroup>
<ProposalFormSubmit isSubmitting={isSubmitting} />
<ProposalFormDownloadJson downloadJson={viewJson} />
<ProposalFormTransactionDialog
finalizedProposal={finalizedProposal}
TransactionDialog={Dialog}
@ -138,7 +143,6 @@ export const ProposeRaw = () => {
</div>
</>
)}
</VegaWalletContainer>
</AsyncRenderer>
/>
);
};

View File

@ -111,6 +111,7 @@ describe('Propose Update Asset', () => {
expect(screen.getByTestId('proposal-vote-deadline')).toBeTruthy();
expect(screen.getByTestId('proposal-enactment-deadline')).toBeTruthy();
expect(screen.getByTestId('proposal-submit')).toBeTruthy();
expect(screen.getByTestId('proposal-download-json')).toBeTruthy();
expect(screen.getByTestId('proposal-transaction-dialog')).toBeTruthy();
});
});

View File

@ -20,13 +20,14 @@ import {
ProposalFormTerms,
ProposalFormTitle,
ProposalFormTransactionDialog,
ProposalFormDownloadJson,
ProposalFormVoteAndEnactmentDeadline,
} from '../../components/propose';
import { ProposalMinRequirements } from '../../components/shared';
import { AsyncRenderer, ExternalLink } from '@vegaprotocol/ui-toolkit';
import { Heading } from '../../../../components/heading';
import { VegaWalletContainer } from '../../../../components/vega-wallet-container';
import { ProposalUserAction } from '../../components/shared';
import { downloadJson } from '../../../../lib/download-json';
export interface UpdateAssetProposalFormFields {
proposalVoteDeadline: string;
@ -60,10 +61,11 @@ export const ProposeUpdateAsset = () => {
handleSubmit,
formState: { isSubmitting, errors },
setValue,
watch,
} = useForm<UpdateAssetProposalFormFields>();
const { finalizedProposal, submit, Dialog } = useProposalSubmit();
const onSubmit = async (fields: UpdateAssetProposalFormFields) => {
const assembleProposal = (fields: UpdateAssetProposalFormFields) => {
const isVoteDeadlineAtMinimum = doesValueEquateToParam(
fields.proposalVoteDeadline,
params.governance_proposal_updateAsset_minClose
@ -81,7 +83,7 @@ export const ProposeUpdateAsset = () => {
params.governance_proposal_updateAsset_maxEnact
);
await submit({
return {
rationale: {
title: fields.proposalTitle,
description: fields.proposalDescription,
@ -101,7 +103,19 @@ export const ProposeUpdateAsset = () => {
isEnactmentDeadlineAtMaximum
),
},
});
};
};
const onSubmit = async (fields: UpdateAssetProposalFormFields) => {
await submit(assembleProposal(fields));
};
const viewJson = () => {
const formData = watch();
downloadJson(
JSON.stringify(assembleProposal(formData)),
'vega-update-asset-proposal'
);
};
return (
@ -109,11 +123,10 @@ export const ProposeUpdateAsset = () => {
loading={networkParamsLoading}
error={networkParamsError}
data={params}
>
<Heading title={t('UpdateAssetProposal')} />
<VegaWalletContainer>
{() => (
render={(params) => (
<>
<Heading title={t('UpdateAssetProposal')} />
<ProposalMinRequirements
minProposalBalance={
params.governance_proposal_updateAsset_minProposerBalance
@ -166,9 +179,7 @@ export const ProposeUpdateAsset = () => {
errorMessage={errors?.proposalDescription?.message}
/>
<ProposalFormSubheader>
{t('UpdateAsset')}
</ProposalFormSubheader>
<ProposalFormSubheader>{t('UpdateAsset')}</ProposalFormSubheader>
<ProposalFormTerms
registerField={register('proposalTerms', {
@ -204,6 +215,7 @@ export const ProposeUpdateAsset = () => {
/>
<ProposalFormSubmit isSubmitting={isSubmitting} />
<ProposalFormDownloadJson downloadJson={viewJson} />
<ProposalFormTransactionDialog
finalizedProposal={finalizedProposal}
TransactionDialog={Dialog}
@ -212,7 +224,6 @@ export const ProposeUpdateAsset = () => {
</div>
</>
)}
</VegaWalletContainer>
</AsyncRenderer>
/>
);
};

View File

@ -187,6 +187,7 @@ describe('Propose Update Market', () => {
expect(screen.getByTestId('proposal-vote-deadline')).toBeTruthy();
expect(screen.getByTestId('proposal-enactment-deadline')).toBeTruthy();
expect(screen.getByTestId('proposal-submit')).toBeTruthy();
expect(screen.getByTestId('proposal-download-json')).toBeTruthy();
expect(screen.getByTestId('proposal-transaction-dialog')).toBeTruthy();
});

View File

@ -21,6 +21,7 @@ import {
ProposalFormTerms,
ProposalFormTitle,
ProposalFormTransactionDialog,
ProposalFormDownloadJson,
ProposalFormVoteAndEnactmentDeadline,
} from '../../components/propose';
import { ProposalMinRequirements } from '../../components/shared';
@ -34,9 +35,9 @@ import {
Select,
} from '@vegaprotocol/ui-toolkit';
import { Heading } from '../../../../components/heading';
import { VegaWalletContainer } from '../../../../components/vega-wallet-container';
import { ProposalUserAction } from '../../components/shared';
import { useProposalMarketsQueryQuery } from './__generated___/UpdateMarket';
import { downloadJson } from '../../../../lib/download-json';
export interface UpdateMarketProposalFormFields {
proposalVoteDeadline: string;
@ -101,10 +102,11 @@ export const ProposeUpdateMarket = () => {
handleSubmit,
formState: { isSubmitting, errors },
setValue,
watch,
} = useForm<UpdateMarketProposalFormFields>();
const { finalizedProposal, submit, Dialog } = useProposalSubmit();
const onSubmit = async (fields: UpdateMarketProposalFormFields) => {
const assembleProposal = (fields: UpdateMarketProposalFormFields) => {
const isVoteDeadlineAtMinimum = doesValueEquateToParam(
fields.proposalVoteDeadline,
params.governance_proposal_updateMarket_minClose
@ -122,7 +124,7 @@ export const ProposeUpdateMarket = () => {
params.governance_proposal_updateMarket_maxEnact
);
await submit({
return {
rationale: {
title: fields.proposalTitle,
description: fields.proposalDescription,
@ -145,24 +147,34 @@ export const ProposeUpdateMarket = () => {
isEnactmentDeadlineAtMaximum
),
},
});
};
};
const onSubmit = async (fields: UpdateMarketProposalFormFields) => {
await submit(assembleProposal(fields));
};
const viewJson = () => {
const formData = watch();
downloadJson(
JSON.stringify(assembleProposal(formData)),
'vega-update-market-proposal'
);
};
return (
<AsyncRenderer
loading={networkParamsLoading && marketsLoading}
error={networkParamsError && marketsError}
data={params && marketsData}
>
<Heading title={t('UpdateMarketProposal')} />
<VegaWalletContainer>
{() => (
data={{ ...params, ...marketsData }}
render={(data) => (
<>
<Heading title={t('UpdateMarketProposal')} />
<ProposalMinRequirements
minProposalBalance={
params.governance_proposal_updateMarket_minProposerBalance
data.governance_proposal_updateMarket_minProposerBalance
}
spamProtectionMin={params.spam_protection_proposal_min_tokens}
spamProtectionMin={data.spam_protection_proposal_min_tokens}
userAction={ProposalUserAction.CREATE}
/>
@ -247,7 +259,7 @@ export const ProposeUpdateMarket = () => {
<KeyValueTableRow>
{t('MarketName')}
{
marketsData?.marketsConnection?.edges?.find(
data.marketsConnection?.edges?.find(
({ node: market }) => market.id === selectedMarket
)?.node.tradableInstrument.instrument.name
}
@ -255,7 +267,7 @@ export const ProposeUpdateMarket = () => {
<KeyValueTableRow>
{t('MarketCode')}
{
marketsData?.marketsConnection?.edges?.find(
data.marketsConnection?.edges?.find(
({ node: market }) => market.id === selectedMarket
)?.node.tradableInstrument.instrument.code
}
@ -284,12 +296,8 @@ export const ProposeUpdateMarket = () => {
required: t('Required'),
})}
voteErrorMessage={errors?.proposalVoteDeadline?.message}
voteMinClose={
params.governance_proposal_updateMarket_minClose
}
voteMaxClose={
params.governance_proposal_updateMarket_maxClose
}
voteMinClose={data.governance_proposal_updateMarket_minClose}
voteMaxClose={data.governance_proposal_updateMarket_maxClose}
onEnactMinMax={setValue}
enactmentRegister={register('proposalEnactmentDeadline', {
required: t('Required'),
@ -298,14 +306,15 @@ export const ProposeUpdateMarket = () => {
errors?.proposalEnactmentDeadline?.message
}
enactmentMinClose={
params.governance_proposal_updateMarket_minEnact
data.governance_proposal_updateMarket_minEnact
}
enactmentMaxClose={
params.governance_proposal_updateMarket_maxEnact
data.governance_proposal_updateMarket_maxEnact
}
/>
<ProposalFormSubmit isSubmitting={isSubmitting} />
<ProposalFormDownloadJson downloadJson={viewJson} />
<ProposalFormTransactionDialog
finalizedProposal={finalizedProposal}
TransactionDialog={Dialog}
@ -314,7 +323,6 @@ export const ProposeUpdateMarket = () => {
</div>
</>
)}
</VegaWalletContainer>
</AsyncRenderer>
/>
);
};