Add more info to message details screen

DRY up details markup
pull/5/head
J M Rossy 2 years ago
parent 78db2d656a
commit 4947a31219
  1. 2
      src/components/icons/ChainIcon.tsx
  2. 325
      src/features/search/MessageDetails.tsx
  3. 3
      src/utils/chains.ts
  4. 5
      src/utils/time.ts

@ -15,6 +15,7 @@ import Celo from '../../images/logos/celo.svg';
import EthMainnet from '../../images/logos/eth-mainnet.svg';
import Optimism from '../../images/logos/optimism.svg';
import Polygon from '../../images/logos/polygon.svg';
import { getChainName } from '../../utils/chains';
const CHAIN_TO_ICON = {
[chain.arbitrum.id]: Arbitrum,
@ -38,6 +39,7 @@ function _ChainIcon({
<div
style={{ width: `${size}px`, height: `${size}px` }}
className="flex items-center justify-center rounded-full bg-beige-500 transition-all"
title={getChainName(chainId)}
>
<Image
src={imageSrc}

@ -10,11 +10,13 @@ import { ChainToChain } from '../../components/icons/ChainToChain';
import { HelpIcon } from '../../components/icons/HelpIcon';
import { useBackgroundBanner } from '../../components/layout/BackgroundBanner';
import { Card } from '../../components/layout/Card';
import { chainToDomain } from '../../consts/domains';
import CheckmarkIcon from '../../images/icons/checkmark-circle.svg';
import ErrorCircleIcon from '../../images/icons/error-circle.svg';
import { MessageStatus } from '../../types';
import { MessageStatus, PartialTransactionReceipt } from '../../types';
import { getChainName } from '../../utils/chains';
import { logger } from '../../utils/logger';
import { getHumanReadableTimeString } from '../../utils/time';
import { getDateTimeString } from '../../utils/time';
import { useInterval } from '../../utils/timeout';
import { PLACEHOLDER_MESSAGES } from './placeholderMessages';
@ -45,14 +47,6 @@ export function MessageDetails({ messageId }: { messageId: string }) {
originTransaction,
destinationTransaction,
} = message;
const originTxExplorerLink = getTxExplorerLink(
originChainId,
originTransaction?.transactionHash,
);
const destinationTxExplorerLink = getTxExplorerLink(
destinationChainId,
destinationTransaction?.transactionHash,
);
const { bannerClassName, setBannerClassName } = useBackgroundBanner();
useEffect(() => {
@ -113,22 +107,103 @@ export function MessageDetails({ messageId }: { messageId: string }) {
)}
</div>
<div className="flex flex-wrap items-center justify-between mt-5 gap-4">
<Card classes="flex-1 min-w-fit space-y-4">
<div className="flex items-center justify-between">
<div className="relative -top-px -left-0.5">
<ChainIcon chainId={originChainId} />
</div>
<div className="flex items-center pb-1">
<h3 className="text-gray-500 font-medium text-md mr-2">
Origin Transaction
</h3>
<HelpIcon size={16} text={helpText.origin} />
</div>
<TransactionCard
title="Origin Transaction"
chainId={originChainId}
status={status}
transaction={originTransaction}
help={helpText.origin}
shouldBlur={shouldBlur}
/>
<TransactionCard
title="Destination Transaction"
chainId={destinationChainId}
status={status}
transaction={destinationTransaction}
help={helpText.destination}
shouldBlur={shouldBlur}
/>
<DetailsCard
originChainId={originChainId}
destinationChainId={destinationChainId}
sender={sender}
recipient={recipient}
body={body}
shouldBlur={shouldBlur}
/>
</div>
</>
);
}
function StatusHeader({
text,
fetching,
children,
}: PropsWithChildren<{ text: string; fetching: boolean }>) {
return (
<div className="flex items-center">
<h3 className="text-white text-lg mr-3">{text}</h3>
{fetching || !children ? (
<div className="w-7 h-7 overflow-hidden flex items-center justify-center">
<div className="scale-[35%]">
<Spinner white={true} />
</div>
</div>
) : (
children
)}
</div>
);
}
interface TransactionCardProps {
title: string;
chainId: number;
status: MessageStatus;
transaction?: PartialTransactionReceipt;
help: string;
shouldBlur: boolean;
}
function TransactionCard({
title,
chainId,
status,
transaction,
help,
shouldBlur,
}: TransactionCardProps) {
const txExplorerLink = getTxExplorerLink(
chainId,
transaction?.transactionHash,
);
return (
<Card classes="flex-1 min-w-fit space-y-4">
<div className="flex items-center justify-between">
<div className="relative -top-px -left-0.5">
<ChainIcon chainId={chainId} />
</div>
<div className="flex items-center pb-1">
<h3 className="text-gray-500 font-medium text-md mr-2">{title}</h3>
<HelpIcon size={16} text={help} />
</div>
</div>
{transaction ? (
<>
<ValueRow
label="Chain:"
labelWidth="w-16"
display={`${getChainName(chainId)} (${chainId} / ${
chainToDomain[chainId]
})`}
displayWidth="w-44 sm:w-56"
blurValue={shouldBlur}
/>
<ValueRow
label="Tx hash:"
labelWidth="w-16"
display={originTransaction.transactionHash}
display={transaction.transactionHash}
displayWidth="w-44 sm:w-56"
showCopy={true}
blurValue={shouldBlur}
@ -136,7 +211,7 @@ export function MessageDetails({ messageId }: { messageId: string }) {
<ValueRow
label="From:"
labelWidth="w-16"
display={originTransaction.from}
display={transaction.from}
displayWidth="w-44 sm:w-56"
showCopy={true}
blurValue={shouldBlur}
@ -144,153 +219,99 @@ export function MessageDetails({ messageId }: { messageId: string }) {
<ValueRow
label="Block:"
labelWidth="w-16"
display={`${
originTransaction.blockNumber
} (${getHumanReadableTimeString(originTransaction.timestamp)})`}
display={`${transaction.blockNumber} (${getDateTimeString(
transaction.timestamp,
)})`}
displayWidth="w-44 sm:w-56"
blurValue={shouldBlur}
/>
{originTxExplorerLink && (
{txExplorerLink && (
<a
className="block text-sm text-gray-500 pl-px underline"
href={originTxExplorerLink}
href={txExplorerLink}
target="_blank"
rel="noopener noreferrer"
>
View in block explorer
</a>
)}
</Card>
<Card classes="flex-1 min-w-fit space-y-4">
<div className="flex items-center justify-between">
<div className="relative -top-px -left-0.5">
<ChainIcon chainId={destinationChainId} />
</div>
<div className="flex items-center pb-1">
<h3 className="text-gray-500 font-medium text-md mr-2">
Destination Transaction
</h3>
<HelpIcon size={16} text={helpText.destination} />
</div>
</div>
{destinationTransaction ? (
<>
<ValueRow
label="Tx hash:"
labelWidth="w-16"
display={destinationTransaction.transactionHash}
displayWidth="w-44 sm:w-56"
showCopy={true}
blurValue={shouldBlur}
/>
<ValueRow
label="From:"
labelWidth="w-16"
display={destinationTransaction.from}
displayWidth="w-44 sm:w-56"
showCopy={true}
blurValue={shouldBlur}
/>
<ValueRow
label="Block:"
labelWidth="w-16"
display={`${
destinationTransaction.blockNumber
} (${getHumanReadableTimeString(
destinationTransaction.timestamp,
)})`}
displayWidth="w-44 sm:w-56"
blurValue={shouldBlur}
/>
{destinationTxExplorerLink && (
<a
className="block text-sm text-gray-500 pl-px underline"
href={destinationTxExplorerLink}
target="_blank"
rel="noopener noreferrer"
>
View in block explorer
</a>
)}
</>
) : (
<div className="flex flex-col items-center py-6">
<div className="text-gray-500">
{status === MessageStatus.Failing
? 'Destination chain transaction currently failing'
: 'Destination chain transaction still in progress'}
</div>
<Spinner classes="mt-4" />
</div>
)}
</Card>
</div>
<Card classes="mt-4 space-y-4">
<div className="flex items-center justify-between">
<div className="relative -top-px -left-0.5">
<ChainToChain
originChainId={originChainId}
destinationChainId={destinationChainId}
/>
</div>
<div className="flex items-center pb-1">
<h3 className="text-gray-500 font-medium text-md mr-2">
Message Details
</h3>
<HelpIcon size={16} text={helpText.details} />
</div>
</div>
<ValueRow
label="Sender to outbox:"
labelWidth="w-24 sm:w-36"
display={sender}
displayWidth="w-48 sm:w-80"
showCopy={true}
blurValue={shouldBlur}
/>
<ValueRow
label="Recipient from outbox:"
labelWidth="w-24 sm:w-36"
display={recipient}
displayWidth="w-48 sm:w-80"
showCopy={true}
blurValue={shouldBlur}
/>
<div>
<label className="text-sm text-gray-500">Message content:</label>
<div className="relative max-w-full break-words py-2 pl-2 pr-9 mt-2 bg-gray-100 text-sm font-mono rounded">
{body}
<CopyButton
copyValue={body}
width={15}
height={15}
classes="absolute top-2 right-2 opacity-70"
/>
</>
) : (
<div className="flex flex-col items-center py-6">
<div className="text-gray-500">
{status === MessageStatus.Failing
? 'Destination chain transaction currently failing'
: 'Destination chain transaction still in progress'}
</div>
<Spinner classes="mt-4" />
</div>
</Card>
</>
)}
</Card>
);
}
function StatusHeader({
text,
fetching,
children,
}: PropsWithChildren<{ text: string; fetching: boolean }>) {
interface DetailsCardProps {
originChainId: number;
destinationChainId: number;
sender: string;
recipient: string;
body: string;
shouldBlur: boolean;
}
function DetailsCard({
originChainId,
destinationChainId,
sender,
recipient,
body,
shouldBlur,
}: DetailsCardProps) {
return (
<div className="flex items-center">
<h3 className="text-white text-lg mr-3">{text}</h3>
{fetching || !children ? (
<div className="w-7 h-7 overflow-hidden flex items-center justify-center">
<div className="scale-[35%]">
<Spinner white={true} />
</div>
<Card classes="mt-4 space-y-4">
<div className="flex items-center justify-between">
<div className="relative -top-px -left-0.5">
<ChainToChain
originChainId={originChainId}
destinationChainId={destinationChainId}
/>
</div>
) : (
children
)}
</div>
<div className="flex items-center pb-1">
<h3 className="text-gray-500 font-medium text-md mr-2">
Message Details
</h3>
<HelpIcon size={16} text={helpText.details} />
</div>
</div>
<ValueRow
label="Sender:"
labelWidth="w-20"
display={sender}
displayWidth="w-48 sm:w-80"
showCopy={true}
blurValue={shouldBlur}
/>
<ValueRow
label="Recipient:"
labelWidth="w-20"
display={recipient}
displayWidth="w-48 sm:w-80"
showCopy={true}
blurValue={shouldBlur}
/>
<div>
<label className="text-sm text-gray-500">Message content:</label>
<div className="relative max-w-full break-words py-2 pl-2 pr-9 mt-2 bg-gray-100 text-sm font-mono rounded">
{body}
<CopyButton
copyValue={body}
width={15}
height={15}
classes="absolute top-2 right-2 opacity-70"
/>
</div>
</div>
</Card>
);
}

@ -1,5 +1,6 @@
import { allChains } from '../consts/networksConfig';
export function getChainName(chainId: number) {
export function getChainName(chainId?: number) {
if (!chainId) return 'unknown';
return allChains.find((c) => c.id === chainId)?.name || 'unknown';
}

@ -26,3 +26,8 @@ export function getHumanReadableTimeString(timestamp: number) {
const date = new Date(timestamp);
return date.toLocaleDateString();
}
export function getDateTimeString(timestamp: number) {
const date = new Date(timestamp);
return `${date.toLocaleTimeString()} ${date.toLocaleDateString()}`;
}

Loading…
Cancel
Save