Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Explorer transfer table1 #3101

Merged
merged 16 commits into from
Jul 11, 2022
7 changes: 4 additions & 3 deletions explorer/client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,16 @@
},
"dependencies": {
"@mysten/sui.js": "file:../../sdk/typescript",
"@tanstack/react-table": "^8.1.4",
"bn.js": "^5.2.0",
"classnames": "^2.3.1",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-ga4": "^1.4.1",
"react-json-view": "^1.21.3",
"react-router-dom": "^6.2.1",
"vanilla-cookieconsent": "^2.8.0",
"web-vitals": "^2.1.4",
"react-json-view": "^1.21.3",
"bn.js": "^5.2.0"
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "react-scripts start",
Expand Down
3 changes: 3 additions & 0 deletions explorer/client/src/assets/SVGIcons/failed.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions explorer/client/src/assets/SVGIcons/forward-arrow-dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions explorer/client/src/assets/SVGIcons/forward-arrow.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions explorer/client/src/assets/SVGIcons/success.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 9 additions & 1 deletion explorer/client/src/components/longtext/Longtext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import { useCallback, useState, useContext } from 'react';
import { Link, useNavigate } from 'react-router-dom';

import { ReactComponent as ContentForwardArrowDark } from '../../assets/SVGIcons/forward-arrow-dark.svg';
import { ReactComponent as ContentCopyIcon } from '../../assets/content_copy_black_18dp.svg';
import { NetworkContext } from '../../context';
import { navigateWithUnknown } from '../../utils/searchUtil';
Expand All @@ -17,6 +18,7 @@ function Longtext({
isLink = true,
alttext = '',
isCopyButton = true,
showIconButton = false,
}: {
text: string;
category:
Expand All @@ -28,6 +30,7 @@ function Longtext({
isLink?: boolean;
alttext?: string;
isCopyButton?: boolean;
showIconButton?: boolean;
}) {
const [isCopyIcon, setCopyIcon] = useState(true);

Expand All @@ -42,6 +45,7 @@ function Longtext({
}, [setCopyIcon, text]);

let icon;
let iconButton = <></>;

if (isCopyButton) {
if (pleaseWait) {
Expand All @@ -59,6 +63,10 @@ function Longtext({
icon = <></>;
}

if (showIconButton) {
iconButton = <ContentForwardArrowDark />;
}

const navigateUnknown = useCallback(() => {
setPleaseWait(true);
navigateWithUnknown(text, navigate, network).then(() =>
Expand Down Expand Up @@ -97,7 +105,7 @@ function Longtext({
className={styles.longtext}
to={`/${category}/${encodeURIComponent(text)}`}
>
{alttext ? alttext : text}
{alttext ? alttext : text} {iconButton}
</Link>
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.networkstats {
@apply bg-[#F7F8F8] p-5 font-[500] text-[#767A81] text-[13px] leading-4 uppercase grid md:grid-cols-2 grid-cols-1 gap-10;
}

.statsitem {
@apply flex justify-between items-center leading-6 text-left;
}

.stats {
@apply text-black text-[16px];
}
77 changes: 77 additions & 0 deletions explorer/client/src/components/network-stats/SuiNetworkStats.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright (c) 2022, Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

import { IS_STATIC_ENV } from '../../utils/envUtil';

import styles from './SuiNetworkStats.module.css';

//TODO add the backend service to get all Network stats data
function SuiNetworkCard({ count }: { count: number | string }) {
const totalStatsData = [
{
title: 'TOTAL Objects',
value: '372.5M',
},
{
title: 'TOTAL MODULES',
value: '153,510',
},
{
title: 'TOTAL BYTES STORED',
value: '2.591B',
},
{
title: 'TOTAL TRANSACTIONS',
value: count,
},
];

const currentStatsData = [
{
title: 'CURRENT SUI PRICE',
value: '$26.45',
},
{
title: 'Current Epoch',
value: '142,215',
},
{
title: 'CURRENT VALIDATORS',
value: '15,482',
},
{
title: 'CURRENT TPS',
value: '2,125',
},
];

return (
<div className={styles.networkstats}>
<div className={styles.statsitems}>
{totalStatsData.map((item, idx) => (
<div className={styles.statsitem} key={idx}>
{item.title}
<span className={styles.stats}>{item.value}</span>
</div>
))}
</div>
<div className={styles.statsitems}>
{currentStatsData.map((item, idx) => (
<div className={styles.statsitem} key={idx}>
{item.title}
<span className={styles.stats}>{item.value}</span>
</div>
))}
</div>
</div>
);
}

function SuiNetworkCardStatic() {
return <SuiNetworkCard count={3030} />;
}

const SuiNetworkStats = ({ count }: { count: number }) =>
IS_STATIC_ENV ? <SuiNetworkCardStatic /> : <SuiNetworkCard count={count} />;

export default SuiNetworkStats;
33 changes: 33 additions & 0 deletions explorer/client/src/components/table/TableCard.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
.content {
@apply container overflow-x-auto text-left text-[#4E555D];
}

.table {
@apply w-full text-sm text-left text-[#4E555D] overflow-x-auto min-w-max;

border-bottom: 1px solid #f0f1f2;
}

.table th {
@apply text-left font-normal uppercase text-[#767A81] text-xs;
}

.table td {
@apply pr-5 text-[#4E555D];
}

.table tbody tr {
@apply space-y-10 mt-10;
}

.addresses {
@apply flex flex-wrap;
}

.addresses svg {
@apply mr-1;
}

.tablespacing {
@apply pb-1 pt-1;
}
170 changes: 170 additions & 0 deletions explorer/client/src/components/table/TableCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
// Copyright (c) 2022, Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0
import {
flexRender,
getCoreRowModel,
useReactTable,
} from '@tanstack/react-table';
import { useMemo } from 'react';

import { ReactComponent as ContentFailedStatus } from '../../assets/SVGIcons/failed.svg';
import { ReactComponent as ContentForwardArrow } from '../../assets/SVGIcons/forward-arrow.svg';
import { ReactComponent as ContentSuccessStatus } from '../../assets/SVGIcons/success.svg';
import Longtext from '../../components/longtext/Longtext';

import type { ExecutionStatusType, TransactionKindName } from '@mysten/sui.js';

import styles from './TableCard.module.css';

type Link = {
url: string;
name?: string;
copy?: boolean;
category?: string;
isLink?: boolean;
};

type TableColumn = {
headerLabel: string;
accessorKey: string;
};
// TODO: update Link to use Tuple type
// type Links = [Link, Link?];
type Links = Link[];

// support multiple types with sepcial handling for 'addresses'/links and status
stella3d marked this conversation as resolved.
Show resolved Hide resolved
type TxType = {
[key: string]:
| string
| number
| boolean
| Links
| React.ReactElement
| {
txTypeName: TransactionKindName | undefined;
status: ExecutionStatusType;
};
};

function TableCard({
Jibz1 marked this conversation as resolved.
Show resolved Hide resolved
tabledata,
}: {
tabledata: {
data: TxType[];
columns: TableColumn[];
};
}) {
const data = useMemo(() => tabledata.data, [tabledata.data]);
// Use Columns to create a table
const columns = useMemo(
() =>
tabledata.columns.map((column) => ({
accessorKey: column.accessorKey,
id: column.accessorKey,
cell: (info: any) => {
const content = info.getValue();
// default types
if (
typeof content === 'string' ||
typeof content === 'number' ||
typeof content === 'boolean'
) {
return info.getValue();
}

// handle multple links in one cell
stella3d marked this conversation as resolved.
Show resolved Hide resolved
if (Array.isArray(content)) {
return (
<section className={styles.addresses}>
{content.map((itm, idx) => (
<div key={idx + itm.url}>
<Longtext
text={itm.url}
alttext={itm.name}
category={itm.category || 'unknown'}
isLink={itm?.isLink}
isCopyButton={itm?.copy}
/>
{idx !== content.length - 1 && (
<ContentForwardArrow />
)}
</div>
))}
</section>
);
}
// Special handling for status
if (typeof content === 'object' && content !== null) {
// TODO: Not sure to allow HTML elements in the table
// Handle HTML elements
if (!content.txTypeName) return <>{content}</>;

return (
<>
{content.status === 'success' ? (
<ContentSuccessStatus />
) : (
<ContentFailedStatus />
)}{' '}
{content.txTypeName}
</>
);
}
return '';
},
header: column.headerLabel,
})),
[tabledata.columns]
);
const table = useReactTable({
data,
columns,
getCoreRowModel: getCoreRowModel(),
});

return (
<div className={styles.content}>
<table className={styles.table}>
<thead>
{table.getHeaderGroups().map((headerGroup) => (
<tr key={headerGroup.id}>
{headerGroup.headers.map((header) => (
<th
key={header.id}
colSpan={header.colSpan}
scope="col"
>
{header.isPlaceholder
? null
: flexRender(
header.column.columnDef.header,
header.getContext()
)}
</th>
))}
</tr>
))}
</thead>
<tbody>
{table.getRowModel().rows.map((row) => (
<tr key={row.id}>
{row.getVisibleCells().map((cell) => (
<td
key={cell.id}
className={styles.tablespacing}
>
{flexRender(
cell.column.columnDef.cell,
cell.getContext()
)}
</td>
))}
</tr>
))}
</tbody>
</table>
</div>
);
}

export default TableCard;
Loading