Implement components for debug message result

pull/4/head
J M Rossy 2 years ago
parent ab4a60c1d8
commit f976161642
  1. 8
      src/components/nav/Header.tsx
  2. 83
      src/features/debugger/TxDebugger.tsx
  3. 9
      src/features/debugger/debugMessage.ts
  4. 2
      src/features/search/MessageSearch.tsx

@ -32,7 +32,7 @@ export function Header({ pathName }: { pathName: string }) {
</div> </div>
</a> </a>
</Link> </Link>
<div className="hidden sm:flex sm:space-x-8 sm:items-center md:space-x-10"> <nav className="hidden sm:flex sm:space-x-8 sm:items-center md:space-x-10">
<Link href="/"> <Link href="/">
<a className={styles.navLink + (pathName === '/' ? ' underline' : '')}>Home</a> <a className={styles.navLink + (pathName === '/' ? ' underline' : '')}>Home</a>
</Link> </Link>
@ -45,7 +45,7 @@ export function Header({ pathName }: { pathName: string }) {
About About
</a> </a>
<NetworkSelector /> <NetworkSelector />
</div> </nav>
<div className="relative flex item-center sm:hidden mr-2"> <div className="relative flex item-center sm:hidden mr-2">
<button className="hover:opactiy-70 transition-all" {...buttonProps}> <button className="hover:opactiy-70 transition-all" {...buttonProps}>
<Image src={HamburgerIcon} width={22} height={22} /> <Image src={HamburgerIcon} width={22} height={22} />
@ -53,7 +53,7 @@ export function Header({ pathName }: { pathName: string }) {
</div> </div>
</div> </div>
{/* Dropdown menu, used on mobile */} {/* Dropdown menu, used on mobile */}
<div className={`${styles.dropdownContainer} ${!isOpen && 'hidden'} right-0`} role="menu"> <nav className={`${styles.dropdownContainer} ${!isOpen && 'hidden'} right-0`} role="menu">
<Link href="/"> <Link href="/">
<a {...itemProps[0]} className={styles.dropdownOption} onClick={closeDropdown}> <a {...itemProps[0]} className={styles.dropdownOption} onClick={closeDropdown}>
<DropdownItemContent icon={HouseIcon} text="Home" /> <DropdownItemContent icon={HouseIcon} text="Home" />
@ -84,7 +84,7 @@ export function Header({ pathName }: { pathName: string }) {
> >
<DropdownItemContent icon={InfoIcon} text="About" /> <DropdownItemContent icon={InfoIcon} text="About" />
</a> </a>
</div> </nav>
</header> </header>
); );
} }

@ -1,7 +1,9 @@
import { useQuery } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import Image from 'next/future/image';
import { useState } from 'react'; import { useState } from 'react';
import { Fade } from '../../components/animation/Fade'; import { Fade } from '../../components/animation/Fade';
import { CopyButton } from '../../components/buttons/CopyButton';
import { SearchBar } from '../../components/search/SearchBar'; import { SearchBar } from '../../components/search/SearchBar';
import { import {
NoSearchError, NoSearchError,
@ -10,12 +12,13 @@ import {
SearchUnknownError, SearchUnknownError,
} from '../../components/search/SearchError'; } from '../../components/search/SearchError';
import { envDisplayValue } from '../../consts/environments'; import { envDisplayValue } from '../../consts/environments';
import ShrugIcon from '../../images/icons/shrug.svg';
import { useStore } from '../../store'; import { useStore } from '../../store';
import useDebounce from '../../utils/debounce'; import useDebounce from '../../utils/debounce';
import { sanitizeString } from '../../utils/string'; import { sanitizeString } from '../../utils/string';
import { isValidSearchQuery } from '../search/utils'; import { isValidSearchQuery } from '../search/utils';
import { debugMessageForHash } from './debugMessage'; import { MessageDebugResult, TxDebugStatus, debugMessageForHash } from './debugMessage';
export function TxDebugger() { export function TxDebugger() {
const environment = useStore((s) => s.environment); const environment = useStore((s) => s.environment);
@ -49,11 +52,15 @@ export function TxDebugger() {
placeholder="Search transaction hash to debug message" placeholder="Search transaction hash to debug message"
/> />
<div className="w-full h-[38.05rem] mt-5 bg-white shadow-md border border-blue-50 rounded overflow-auto relative"> <div className="w-full h-[38.05rem] mt-5 bg-white shadow-md border border-blue-50 rounded overflow-auto relative">
<div className="px-2 py-3 sm:px-4 md:px-5 md:py-3 flex items-center justify-between border-b border-gray-100"> <div className="px-2 py-3 sm:px-4 md:px-5 flex items-center justify-between border-b border-gray-100">
<h2 className="text-gray-600">{`Transaction Debugger (${envDisplayValue[environment]})`}</h2> <h2 className="text-gray-600">{`Transaction Debugger (${envDisplayValue[environment]})`}</h2>
</div> </div>
<Fade show={isValidInput && !hasError && !!data}>{JSON.stringify(data)}</Fade> <Fade show={isValidInput && !hasError && !!data}>
<div className="px-2 sm:px-4 md:px-5">
<DebugResult result={data} />
</div>
</Fade>
<SearchEmptyError <SearchEmptyError
show={isValidInput && !hasError && !fetching && !data} show={isValidInput && !hasError && !fetching && !data}
hasInput={hasInput} hasInput={hasInput}
@ -66,3 +73,73 @@ export function TxDebugger() {
</> </>
); );
} }
function DebugResult({ result }: { result: MessageDebugResult | null | undefined }) {
if (!result) return null;
if (result.status === TxDebugStatus.NotFound) {
return (
<div className="py-8 flex flex-col items-center">
<Image src={ShrugIcon} width={110} className="opacity-80" />
<h2 className="mt-4 text-lg text-gray-600">No transaction found</h2>
<p className="mt-4 leading-relaxed">{result.details}</p>
</div>
);
}
if (result.status === TxDebugStatus.NoMessages) {
return (
<div className="py-8 flex flex-col items-center">
<Image src={ShrugIcon} width={110} className="opacity-80" />
<h2 className="mt-4 text-lg text-gray-600">No message found</h2>
<p className="mt-4 leading-relaxed">{result.details}</p>
<TxExplorerLink href={result.explorerLink} />
</div>
);
}
if (result.status === TxDebugStatus.MessagesFound) {
return (
<>
{result.messageDetails.map((m, i) => (
<div className="border-b border-gray-200 py-4" key={`message-${i}`}>
<h2 className="text-lg text-gray-600">{`Message ${i + 1} / ${
result.messageDetails.length
}`}</h2>
<p className="mt-2 leading-relaxed">{m.summary}</p>
<div className="mt-2 text-sm">
{Array.from(m.properties.entries()).map(([key, val]) => (
<div className="flex mt-1" key={`message-${i}-prop-${key}`}>
<label className="text-gray-600 w-32">{key}</label>
<div className="relative ml-2 truncate max-w-xs sm:max-w-sm md:max-w-lg">
{val}
</div>
{val.length > 20 && (
<CopyButton copyValue={val} width={12} height={12} classes="ml-2" />
)}
</div>
))}
</div>
</div>
))}
<TxExplorerLink href={result.explorerLink} />
</>
);
}
return null;
}
function TxExplorerLink({ href }: { href: string | undefined }) {
if (!href) return null;
return (
<a
className="block my-5 text-blue-600 hover:text-blue-500 underline underline-offset-4"
href={href}
target="_blank"
rel="noopener noreferrer"
>
View transaction in explorer
</a>
);
}

@ -55,7 +55,10 @@ export interface DebugMessagesFoundResult {
messageDetails: MessageDetails[]; messageDetails: MessageDetails[];
} }
type MessageDebugResult = DebugNotFoundResult | DebugNoMessagesResult | DebugMessagesFoundResult; export type MessageDebugResult =
| DebugNotFoundResult
| DebugNoMessagesResult
| DebugMessagesFoundResult;
export async function debugMessageForHash( export async function debugMessageForHash(
txHash: string, txHash: string,
@ -89,9 +92,9 @@ export async function debugMessageForHash(
logger.debug(`Found ${dispatchedMessages.length} messages`); logger.debug(`Found ${dispatchedMessages.length} messages`);
const messageDetails: MessageDetails[] = []; const messageDetails: MessageDetails[] = [];
for (let i = 0; i < dispatchedMessages.length; i++) { for (let i = 0; i < dispatchedMessages.length; i++) {
logger.debug(`Checking message ${i} of ${dispatchedMessages.length}`); logger.debug(`Checking message ${i + 1} of ${dispatchedMessages.length}`);
messageDetails.push(await checkMessage(core, multiProvider, dispatchedMessages[i])); messageDetails.push(await checkMessage(core, multiProvider, dispatchedMessages[i]));
logger.debug(`Done checking message ${i}`); logger.debug(`Done checking message ${i + 1}`);
} }
return { return {
status: TxDebugStatus.MessagesFound, status: TxDebugStatus.MessagesFound,

@ -91,7 +91,7 @@ export function MessageSearch() {
/> />
<div className="w-full h-[38.05rem] mt-5 bg-white shadow-md border border-blue-50 rounded overflow-auto relative"> <div className="w-full h-[38.05rem] mt-5 bg-white shadow-md border border-blue-50 rounded overflow-auto relative">
{/* Content header and filter bar */} {/* Content header and filter bar */}
<div className="px-2 py-3 sm:px-4 md:px-5 md:py-3 flex items-center justify-between border-b border-gray-100"> <div className="px-2 py-3 sm:px-4 md:px-5 flex items-center justify-between border-b border-gray-100">
<h2 className="text-gray-600">{!hasInput ? 'Latest Messages' : 'Search Results'}</h2> <h2 className="text-gray-600">{!hasInput ? 'Latest Messages' : 'Search Results'}</h2>
<div className="flex items-center space-x-1 sm:space-x-2 md:space-x-3"> <div className="flex items-center space-x-1 sm:space-x-2 md:space-x-3">
<div className="w-px h-8 bg-gray-100"></div> <div className="w-px h-8 bg-gray-100"></div>

Loading…
Cancel
Save