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

Initialize Account Dashboard Page #1811

Merged
merged 32 commits into from
Nov 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
024d2c9
refactor: move Suspense component into webb-ui-components
AtelyPham Oct 25, 2023
1b3ba55
feat: add note account to sidebar and implement authenticated route
AtelyPham Oct 25, 2023
9e49e9f
fix: sidebar link issue
AtelyPham Oct 25, 2023
56ea282
feat: add Account to sidebar and fix the link warnings
AtelyPham Oct 26, 2023
2917ba3
refactor: add side bar hook to access the note account state
AtelyPham Oct 27, 2023
c374dc4
feat: add isDisabled prop to SideBar.Item and SideBar.SubItem
AtelyPham Oct 27, 2023
646cc5f
chore: move account components to account page
AtelyPham Oct 27, 2023
3a87dba
fix: layout shift on sidebar and remove auto collapse dropdown when i…
AtelyPham Oct 28, 2023
bd74b62
chore: consolidate note download methods
AtelyPham Oct 28, 2023
0a5b81b
refactor: note action logic in hook to share between tables
AtelyPham Oct 28, 2023
727bf19
chore: correct icon for breadcrumb
AtelyPham Oct 28, 2023
a8d7758
fix: sidebar active sub menu item does not update when clicking on a …
AtelyPham Oct 28, 2023
4c0f596
refactor: convert active chain selection card to dropdown
AtelyPham Oct 30, 2023
fe44d5a
chore: add logic for switching chains
AtelyPham Oct 30, 2023
db7b46c
fix: unify dropdown margin
AtelyPham Oct 30, 2023
779488a
feat: add total shielded balance section to account summary card
AtelyPham Oct 30, 2023
e5cca1c
feat: adding UI actions for account summary card
AtelyPham Oct 30, 2023
71af129
refactor: unifying config into params provider
AtelyPham Oct 30, 2023
43fc494
feat: add hidden value feature to account dashboard
AtelyPham Oct 31, 2023
12804f1
chore: add logic to handle token change and render shielded balance
AtelyPham Oct 31, 2023
8a3590d
chore: hidden value for note account tables
AtelyPham Oct 31, 2023
e68803d
fix: empty state on shielded balances card
AtelyPham Oct 31, 2023
f5b714b
chore: adding amount for withdraw & transfer on note account tables
AtelyPham Oct 31, 2023
f5b6018
Merge branch 'develop' into feat/account-dashboard
AtelyPham Oct 31, 2023
58e37c1
Merge branch 'develop' into trung-tin/init-account-dashboard
AtelyPham Oct 31, 2023
191be79
fix: only check connection after provider has been initialized
AtelyPham Oct 31, 2023
c672176
chore: remove notes and shielded assets filter by active chain
AtelyPham Oct 31, 2023
18f19be
feat: add condition to render view account button or dismiss button
AtelyPham Oct 31, 2023
4d34cdf
chore: add receive modal
vutuanlinh2k2 Nov 2, 2023
8444041
feat: adding logic for connect wallet and create note account when us…
AtelyPham Nov 2, 2023
bcb11b7
chore: remove the old navigate to select active source chain card
AtelyPham Nov 2, 2023
2399adf
chore [skip ci]: add link to note account page for learn more button
AtelyPham Nov 2, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions apps/bridge-dapp/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as Sentry from '@sentry/react';
import { AppEvent, WebbProvider } from '@webb-tools/api-provider-environment';
import { WebbUIProvider } from '@webb-tools/webb-ui-components';
import { FC } from 'react';
import BridgeRoutes from './routes';
import AppRoutes from './routes';

// Singleton app event instance
export const appEvent = new AppEvent();
Expand All @@ -11,7 +11,7 @@ const App: FC = () => {
return (
<WebbUIProvider hasErrorBoudary>
<WebbProvider appEvent={appEvent} applicationName={'Webb DApp'}>
<BridgeRoutes />
<AppRoutes />
</WebbProvider>
</WebbUIProvider>
);
Expand Down
95 changes: 95 additions & 0 deletions apps/bridge-dapp/src/components/Header/ActiveChainDropdown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import { DropdownMenuTrigger as DropdownButton } from '@radix-ui/react-dropdown-menu';
import { useWebContext } from '@webb-tools/api-provider-environment/webb-context/webb-context';
import type { ChainConfig } from '@webb-tools/dapp-config/chains/chain-config.interface';
import getChainFromConfig from '@webb-tools/dapp-config/utils/getChainFromConfig';
import { WebbError, WebbErrorCodes } from '@webb-tools/dapp-types/WebbError';
import { ChainIcon } from '@webb-tools/icons/ChainIcon';
import { calculateTypedChainId } from '@webb-tools/sdk-core/typed-chain-id';
import {
Dropdown,
DropdownBody,
} from '@webb-tools/webb-ui-components/components/Dropdown';
import { MenuItem } from '@webb-tools/webb-ui-components/components/MenuItem';
import { ScrollArea } from '@webb-tools/webb-ui-components/components/ScrollArea';
import ChainButtonCmp from '@webb-tools/webb-ui-components/components/buttons/ChainButton';
import { useWebbUI } from '@webb-tools/webb-ui-components/hooks/useWebbUI';
import { useCallback, useMemo } from 'react';
import useChainsFromRoute from '../../hooks/useChainsFromRoute';
import { useConnectWallet } from '../../hooks/useConnectWallet';

const ActiveChainDropdown = () => {
const { activeChain, activeWallet, apiConfig, switchChain, loading } =
useWebContext();
const { toggleModal } = useConnectWallet();
const { srcTypedChainId } = useChainsFromRoute();
const { notificationApi } = useWebbUI();

const chain = useMemo(() => {
if (activeChain) {
return activeChain;
}

// Default to the chain from route if no active chain
if (typeof srcTypedChainId === 'number' && activeChain !== null) {
return apiConfig.chains[srcTypedChainId];
}
}, [activeChain, apiConfig.chains, srcTypedChainId]);

const selectableChains = useMemo(
() => apiConfig.getSupportedChains({ withEnv: true }),
[apiConfig]
);

const handleSelectChain = useCallback(
async (chainCfg: ChainConfig) => {
const chain = getChainFromConfig(chainCfg);

if (!activeWallet || !chain.wallets.includes(activeWallet.id)) {
toggleModal(true, calculateTypedChainId(chain.chainType, chain.id));
} else {
const api = await switchChain(chain, activeWallet);
if (!api) {
notificationApi.addToQueue({
variant: 'error',
message: WebbError.getErrorMessage(WebbErrorCodes.SwitchChainFailed)
.message,
});
}
}
},
[activeWallet, notificationApi, switchChain, toggleModal]
);

return (
<Dropdown>
<DropdownButton asChild disabled={loading}>
<ChainButtonCmp
chain={chain}
status="success"
placeholder={activeChain === null ? 'Unsupported Chain' : undefined}
textClassname="hidden lg:!block"
/>
</DropdownButton>
<DropdownBody className="mt-2">
<ScrollArea className="h-[var(--dropdown-height)]">
<ul>
{selectableChains.map((chain) => {
return (
<li key={`${chain.chainType}-${chain.id}`}>
<MenuItem
startIcon={<ChainIcon size="lg" name={chain.name} />}
onSelect={() => handleSelectChain(chain)}
>
{chain.name}
</MenuItem>
</li>
);
})}
</ul>
</ScrollArea>
</DropdownBody>
</Dropdown>
);
};

export default ActiveChainDropdown;
37 changes: 0 additions & 37 deletions apps/bridge-dapp/src/components/Header/ChainButton.tsx

This file was deleted.

27 changes: 16 additions & 11 deletions apps/bridge-dapp/src/components/Header/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useWebContext } from '@webb-tools/api-provider-environment';
import { ContrastTwoLine, WebbLogoIcon } from '@webb-tools/icons';
import { WebbLogoIcon } from '@webb-tools/icons';
import {
Breadcrumbs,
BreadcrumbsItem,
Expand All @@ -23,21 +23,22 @@ import {
WEBB_MKT_URL,
} from '@webb-tools/webb-ui-components/constants';
import {
type ComponentProps,
type FC,
useCallback,
useEffect,
useState,
useMemo,
useState,
type ComponentProps,
type FC,
} from 'react';
import { NavLink, useLocation } from 'react-router-dom';
import sidebarProps from '../../constants/sidebar';
import { BREADCRUMBS_RECORD } from '../../constants/breadcrumb';
import useChainsFromRoute from '../../hooks/useChainsFromRoute';
import { useConnectWallet } from '../../hooks/useConnectWallet';
import useSidebarProps from '../../hooks/useSidebarProps';
import ActiveChainDropdown from './ActiveChainDropdown';
import TxProgressDropdown from './TxProgressDropdown';
import { WalletDropdown } from './WalletDropdown';
import { HeaderProps } from './types';
import ChainButton from './ChainButton';

/**
* The statistic `Header` for `Layout` container
Expand All @@ -55,17 +56,21 @@ export const Header: FC<HeaderProps> = () => {

const items = location.pathname.split('/').filter((item) => item !== '');

const sidebarProps = useSidebarProps();

const breadcrumbItems = useMemo(
() =>
items.map((item, index) => {
const preCfgBreadcrumb = BREADCRUMBS_RECORD[item];

return (
<NavLink key={index} to={'/'}>
<NavLink key={index} to={item}>
<BreadcrumbsItem
isLast={index === items.length - 1}
icon={index === 0 ? <ContrastTwoLine size="lg" /> : undefined}
icon={preCfgBreadcrumb?.Icon}
className="capitalize"
>
{index === 0 ? `Hubble ${item}` : item.split('-').join(' ')}
{preCfgBreadcrumb?.label ?? item.split('-').join(' ')}
</BreadcrumbsItem>
</NavLink>
);
Expand Down Expand Up @@ -98,7 +103,7 @@ export const Header: FC<HeaderProps> = () => {
<TxProgressDropdown />

<div className="flex items-center space-x-2">
<ChainButton />
<ActiveChainDropdown />
{isConnecting || loading || !activeWallet || !activeAccount ? (
isMobile ? (
<ConnectWalletMobileButton />
Expand All @@ -109,7 +114,7 @@ export const Header: FC<HeaderProps> = () => {
onClick={() =>
toggleModal(true, srcTypedChainId ?? undefined)
}
className="flex justify-center items-center px-6"
className="flex items-center justify-center px-6"
>
Connect
</Button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,15 @@ import { getExplorerURI } from '@webb-tools/api-provider-environment/transaction
import { useWebContext } from '@webb-tools/api-provider-environment/webb-context';
import TxProgressor from '@webb-tools/webb-ui-components/components/TxProgressor';
import type { TxInfo } from '@webb-tools/webb-ui-components/components/TxProgressor/types';
import type { ButtonProps } from '@webb-tools/webb-ui-components/components/buttons/types';
import type { TransactionItemStatus } from '@webb-tools/webb-ui-components/containers/TransactionProgressCard/types';
import type { FC } from 'react';
import { NOTE_ACCOUNT_PATH } from '../../../constants/paths';

const TxItem: FC<{ tx: Transaction<unknown> }> = ({ tx }) => {
const TxItem: FC<{ tx: Transaction<unknown>; isOnAccountPage?: boolean }> = ({
tx,
isOnAccountPage,
}) => {
const { activeApi, apiConfig, txQueue } = useWebContext();
const { api } = txQueue;

Expand Down Expand Up @@ -48,12 +53,17 @@ const TxItem: FC<{ tx: Transaction<unknown> }> = ({ tx }) => {

const externalUrl = getExternalUrl(blockExplorer, activeApi?.type, tx.txHash);

const btnProps = {
onClick: () => {
api.dismissTransaction(tx.id);
},
children: 'Dismiss',
};
const btnProps = isOnAccountPage
? ({
onClick: () => {
api.dismissTransaction(tx.id);
},
children: 'Dismiss',
} satisfies ButtonProps)
: ({
href: `/#/${NOTE_ACCOUNT_PATH}`,
children: 'View Account',
} satisfies ButtonProps);

return (
<TxProgressor.Root key={tx.id}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,14 @@ import LoadingPill from '@webb-tools/webb-ui-components/components/buttons/Loadi
import type { LoadingPillStatus } from '@webb-tools/webb-ui-components/components/buttons/types';
import type { TransactionItemStatus } from '@webb-tools/webb-ui-components/containers/TransactionProgressCard';
import { useEffect, useMemo, useState } from 'react';
import { useLocation } from 'react-router';
import { NOTE_ACCOUNT_PATH } from '../../../constants/paths';
import useCurrentTx from '../../../hooks/useCurrentTx';
import TxItem from './TxItem';

const TxProgressDropdown = () => {
const { txQueue: txQueue_ } = useWebContext();
const { pathname } = useLocation();

const { txQueue, currentTxId } = txQueue_;

Expand All @@ -25,6 +28,11 @@ const TxProgressDropdown = () => {

const currentTx = useCurrentTx(sortedTxQueue, currentTxId, { latest: true });

const isOnAccountPage = useMemo(
() => pathname.includes(`/${NOTE_ACCOUNT_PATH}`),
[pathname]
);

useEffect(() => {
if (!currentTx) {
return;
Expand Down Expand Up @@ -56,7 +64,9 @@ const TxProgressDropdown = () => {
className="mt-4 -ml-14 max-h-80 w-[30rem] overflow-scroll overflow-x-hidden"
>
{sortedTxQueue.map((tx) => {
return <TxItem key={tx.id} tx={tx} />;
return (
<TxItem key={tx.id} tx={tx} isOnAccountPage={isOnAccountPage} />
);
})}
</DropdownBody>
</Dropdown>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import { useWebContext } from '@webb-tools/api-provider-environment/webb-context';
import { useMemo } from 'react';
import cx from 'classnames';
import { IconWithTooltip } from '@webb-tools/webb-ui-components/components/IconWithTooltip';
import { Avatar } from '@webb-tools/webb-ui-components/components/Avatar';
import { KeyValueWithButton } from '@webb-tools/webb-ui-components/components/KeyValueWithButton';
import { InformationLine } from '@webb-tools/icons/InformationLine';
import { Typography } from '@webb-tools/webb-ui-components/typography/Typography';
import cx from 'classnames';
import { useMemo } from 'react';
import { NOTE_ACCOUNT_DOCS_URL } from '../../../constants/links';
import NoteAccountAvatarWithKey from '../../NoteAccountAvatarWithKey';

const NoteAccountKey = () => {
const { noteManager } = useWebContext();
Expand All @@ -28,21 +26,11 @@ const NoteAccountKey = () => {
)}
>
{keyPairStr ? (
<>
<IconWithTooltip
icon={<Avatar value={keyPairStr} theme="ethereum" />}
content="Note account"
/>

<KeyValueWithButton
className="mt-0.5"
label="Public Key:"
keyValue={keyPairStr}
size="sm"
labelVariant="body1"
valueVariant="body1"
/>
</>
<NoteAccountAvatarWithKey
keyValue={keyPairStr}
label="Public Key:"
iconTooltipContent="Note account public key"
/>
) : (
<>
<div className="p-1 !text-inherit">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,11 @@ export const WalletDropdown: FC<{ account: Account; wallet: WalletConfig }> = ({
<WalletButton
wallet={wallet}
address={account.address}
addressClassname="hidden lg:block"
addressClassname="hidden lg:!block"
/>
</DropdownTrigger>

<DropdownBody className="mt-6 w-[480px] p-4 space-y-4 dark:bg-mono-160">
<DropdownBody className="mt-2 w-[480px] p-4 space-y-4 dark:bg-mono-160">
<div className="flex items-center justify-between">
<div className="flex space-x-2">
{wallet.Logo}
Expand Down
23 changes: 23 additions & 0 deletions apps/bridge-dapp/src/components/HiddenValue.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import useHiddenValue from '../hooks/useHiddenValue';

function HiddenValue(props: {
/** The children must be a string */
children: string;

/** Number of star to display. @default to children.length */
numberOfStars?: number;
}) {
const { numberOfStars } = props;

const [isHidden] = useHiddenValue();

if (isHidden) {
return Array.from({ length: numberOfStars ?? props.children.length })
.map(() => '*')
.join('');
}

return props.children;
}

export default HiddenValue;
Loading