Feat/519: Add copy button to transaction content in explorer (#1016)
* Feat/519: Add copy button to transaction content in explorer * Feat/519: Adjusted copy of the button title * Update apps/explorer/src/app/routes/txs/id/tx-details.tsx Co-authored-by: botond <105208209+notbot00@users.noreply.github.com> Co-authored-by: botond <105208209+notbot00@users.noreply.github.com>
This commit is contained in:
parent
445897eb2b
commit
4b51ef57e9
65
apps/explorer/src/app/routes/txs/id/tx-details.spec.tsx
Normal file
65
apps/explorer/src/app/routes/txs/id/tx-details.spec.tsx
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import { BrowserRouter as Router } from 'react-router-dom';
|
||||||
|
import { render, screen } from '@testing-library/react';
|
||||||
|
import { truncateByChars } from '@vegaprotocol/react-helpers';
|
||||||
|
import { TxDetails, txDetailsTruncateLength } from './tx-details';
|
||||||
|
import type { Result } from '../tendermint-transaction-response.d';
|
||||||
|
|
||||||
|
const pubKey = 'test';
|
||||||
|
const hash = '7416753A30622A9E24A06F0172D6C33A95186B36806D96345C6DC5A23FA3F283';
|
||||||
|
const height = '52987';
|
||||||
|
const tx =
|
||||||
|
'ClMIpeWjmKnn77FNEPedA5J9QhJAOGI3YjQzMWNlMmNhNzc4MWMzMTQ1M2IyYjc0MWYwMTJlNzQ1MzBhZDhjMDgzODVkMWQ1YjRiY2VkMTJiNDc1MhKTAQqAATM5NDFlNmExMzQ3MGVhNTlhNGExNmQzMjRiYzlkZjI5YWZkMzYxMDRiZjQ5MzEwZWMxM2ZiOTMxNTM2NGY3ZjU2ZTQyOTJmYTAyZDlhNTBlZDc0OWE0ZjExMzJiNjM2ZTZmMzQ3YzQ2NjdkYmM5OThmYzcyZjYzYzQxMzU4ZTAzEgx2ZWdhL2VkMjU1MTkYAYB9AtI+QDA5MzFhOGZkOGNjOTM1NDU4ZjQ3MGU0MzVhMDU0MTQzODdjZWE2ZjMyOWQ2NDhiZTg5NGZjZDQ0YmQ1MTdhMmI=';
|
||||||
|
|
||||||
|
const txData = {
|
||||||
|
hash,
|
||||||
|
height,
|
||||||
|
tx,
|
||||||
|
index: 0,
|
||||||
|
tx_result: {
|
||||||
|
code: 0,
|
||||||
|
data: null,
|
||||||
|
log: '',
|
||||||
|
info: '',
|
||||||
|
events: [],
|
||||||
|
gas_wanted: '0',
|
||||||
|
gas_used: '0',
|
||||||
|
codespace: '',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderComponent = (txData: Result) => (
|
||||||
|
<Router>
|
||||||
|
<TxDetails txData={txData} pubKey={pubKey} />
|
||||||
|
</Router>
|
||||||
|
);
|
||||||
|
|
||||||
|
describe('Transaction details', () => {
|
||||||
|
it('Renders the tx hash', () => {
|
||||||
|
render(renderComponent(txData));
|
||||||
|
expect(screen.getByText(hash)).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Renders the pubKey', () => {
|
||||||
|
render(renderComponent(txData));
|
||||||
|
expect(screen.getByText(pubKey)).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Renders the height', () => {
|
||||||
|
render(renderComponent(txData));
|
||||||
|
expect(screen.getByText(height)).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Renders the truncated tx text', () => {
|
||||||
|
render(renderComponent(txData));
|
||||||
|
expect(
|
||||||
|
screen.getByText(
|
||||||
|
truncateByChars(tx, txDetailsTruncateLength, txDetailsTruncateLength)
|
||||||
|
)
|
||||||
|
).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Renders a copy button', () => {
|
||||||
|
render(renderComponent(txData));
|
||||||
|
expect(screen.getByTestId('copy-tx-to-clipboard')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
@ -1,5 +1,5 @@
|
|||||||
import { Routes } from '../../route-names';
|
import { Routes } from '../../route-names';
|
||||||
import type { Result } from '../tendermint-transaction-response.d';
|
import { Button, CopyWithTooltip } from '@vegaprotocol/ui-toolkit';
|
||||||
import {
|
import {
|
||||||
TableWithTbody,
|
TableWithTbody,
|
||||||
TableCell,
|
TableCell,
|
||||||
@ -8,15 +8,16 @@ import {
|
|||||||
} from '../../../components/table';
|
} from '../../../components/table';
|
||||||
import { TruncateInline } from '../../../components/truncate/truncate';
|
import { TruncateInline } from '../../../components/truncate/truncate';
|
||||||
import { t } from '@vegaprotocol/react-helpers';
|
import { t } from '@vegaprotocol/react-helpers';
|
||||||
|
|
||||||
import { HighlightedLink } from '../../../components/highlighted-link';
|
import { HighlightedLink } from '../../../components/highlighted-link';
|
||||||
|
import type { Result } from '../tendermint-transaction-response.d';
|
||||||
|
|
||||||
interface TxDetailsProps {
|
interface TxDetailsProps {
|
||||||
txData: Result | undefined;
|
txData: Result | undefined;
|
||||||
pubKey: string | undefined;
|
pubKey: string | undefined;
|
||||||
className?: string;
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const truncateLength = 30;
|
export const txDetailsTruncateLength = 30;
|
||||||
|
|
||||||
export const TxDetails = ({ txData, pubKey, className }: TxDetailsProps) => {
|
export const TxDetails = ({ txData, pubKey, className }: TxDetailsProps) => {
|
||||||
if (!txData) {
|
if (!txData) {
|
||||||
@ -50,12 +51,25 @@ export const TxDetails = ({ txData, pubKey, className }: TxDetailsProps) => {
|
|||||||
</TableRow>
|
</TableRow>
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
<TableCell>{t('Encoded txn')}</TableCell>
|
<TableCell>{t('Encoded txn')}</TableCell>
|
||||||
<TableCell modifier="bordered" data-testid="encoded-tnx">
|
<TableCell
|
||||||
|
modifier="bordered"
|
||||||
|
data-testid="encoded-tnx"
|
||||||
|
className="flex justify-between"
|
||||||
|
>
|
||||||
<TruncateInline
|
<TruncateInline
|
||||||
text={txData.tx}
|
text={txData.tx}
|
||||||
startChars={truncateLength}
|
startChars={txDetailsTruncateLength}
|
||||||
endChars={truncateLength}
|
endChars={txDetailsTruncateLength}
|
||||||
/>
|
/>
|
||||||
|
<CopyWithTooltip text="">
|
||||||
|
<Button
|
||||||
|
variant="inline-link"
|
||||||
|
prependIconName="duplicate"
|
||||||
|
title={t('Copy tx to clipboard')}
|
||||||
|
onClick={() => navigator.clipboard.writeText(txData.tx)}
|
||||||
|
data-testid="copy-tx-to-clipboard"
|
||||||
|
/>
|
||||||
|
</CopyWithTooltip>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableWithTbody>
|
</TableWithTbody>
|
||||||
|
@ -31,7 +31,7 @@ export function CopyWithTooltip({ children, text }: CopyWithTooltipProps) {
|
|||||||
return (
|
return (
|
||||||
<CopyToClipboard text={text} onCopy={() => setCopied(true)}>
|
<CopyToClipboard text={text} onCopy={() => setCopied(true)}>
|
||||||
{/* Needs this wrapping div as tooltip component interfers with element used to capture click for copy */}
|
{/* Needs this wrapping div as tooltip component interfers with element used to capture click for copy */}
|
||||||
<span>
|
<span className="inline-flex content-center">
|
||||||
<Tooltip description="Copied" open={copied} align="center">
|
<Tooltip description="Copied" open={copied} align="center">
|
||||||
{children}
|
{children}
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
Loading…
Reference in New Issue
Block a user