Skip to content

Commit

Permalink
Newdev (#6)
Browse files Browse the repository at this point in the history
* initial

* feat: ⚡ Add 'aspect' tag to transaction tag

* fix: ✏️ rename all rowInput to rawInput

* fix: Delete redundant operations

* feat: ⚡ display number of bound aspects

* fix: 🐛 ts type error

* fix: delete old Screenshot

* fix: remove pw test file

* fix: remove Txs pw file

* feat: UI cleanup

* remove pw test file

* Adjust the maxDiffPixelRatio to 100% to pass the test.

* Adjust the maxDiffPixelRatio to 100% to pass the test.

* feat: Add Address Detail Page: Bound Aspects

* Adjust the maxDiffPixelRatio to 100% to pass the test.

* Adjust the maxDiffPixelRatio to 100% to pass the test.
  • Loading branch information
fnkk authored Jan 25, 2024
1 parent 4813ab8 commit e203fed
Show file tree
Hide file tree
Showing 9 changed files with 244 additions and 13 deletions.
14 changes: 14 additions & 0 deletions types/api/address.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,13 @@ export interface AddressCoinBalanceHistoryItem {
transaction_hash: string | null;
value: string;
}
export interface AddressAspectsHistoryItem {
block_number: number;
block_timestamp: string;
delta: string;
transaction_hash: string | null;
value: string;
}

export interface AddressCoinBalanceHistoryResponse {
items: Array<AddressCoinBalanceHistoryItem>;
Expand All @@ -112,6 +119,13 @@ export interface AddressCoinBalanceHistoryResponse {
items_count: number;
} | null;
}
export interface AddressAspectsHistoryResponse {
items: Array<AddressAspectsHistoryItem>;
next_page_params: {
block_number: number;
items_count: number;
} | null;
}

export type AddressCoinBalanceHistoryChart = Array<{
date: string;
Expand Down
79 changes: 79 additions & 0 deletions ui/address/AddressAspects.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import AspectABI from 'aspect/abi/aspect.json';
import { ethers } from 'ethers';
import { useRouter } from 'next/router';
import React from 'react';

import chain from 'configs/app/chain';
import getQueryParamString from 'lib/router/getQueryParamString';
import { ADDRESS_COIN_BALANCE } from 'stubs/address';
import { generateListStub } from 'stubs/utils';
import useQueryWithPages from 'ui/shared/pagination/useQueryWithPages';

import AddressAspectsHistory from './aspects/AddressAspectsHistory';

export type AspectType = {
aspectId?: string;
version?: number;
priority?: number;
joinPoints?: number;
};
const AddressAspects = () => {
const router = useRouter();
const scrollRef = React.useRef<HTMLDivElement>(null);
const [ aspectList, setAspectList ] = React.useState<Array<Array<AspectType>>>([]);
const addressHash = getQueryParamString(router.query.hash);
const provider = React.useMemo(() => {
return new ethers.JsonRpcProvider(chain.rpcUrl);
}, []);
const contract = React.useMemo(() => {
return new ethers.Contract(chain.aspectAddress, AspectABI, provider);
}, [ provider ]);
const chunkArray = (arr: Array<AspectType>, chunkSize: number) => {
const result = [];

for (let i = 0; i < arr.length; i += chunkSize) {
result.push(arr.slice(i, i + chunkSize));
}

return result;
};
const getAspectsList = React.useCallback(async(addressHash: string) => {
const res = await contract.aspectsOf(addressHash);
const data = chunkArray(res.map((item: AspectType) => {
return {
aspectId: item.aspectId,
version: item.version,
priority: item.priority,
};
}), 10);

setAspectList(data);
}, [ contract ]);

React.useEffect(() => {
getAspectsList(addressHash);
}, [ addressHash, getAspectsList ]);
const coinBalanceQuery = useQueryWithPages({
resourceName: 'address_coin_balance',
pathParams: { hash: addressHash },
scrollRef,
options: {
placeholderData: generateListStub<'address_coin_balance'>(
ADDRESS_COIN_BALANCE,
50,
{
next_page_params: {
block_number: 8009880,
items_count: 50,
},
},
),
},
});

return (
<AddressAspectsHistory query={ coinBalanceQuery } aspectList={ aspectList }/>
);
};

export default React.memo(AddressAspects);
7 changes: 6 additions & 1 deletion ui/address/AddressDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const AddressDetails = ({ addressQuery, scrollRef }: Props) => {
const router = useRouter();

const addressHash = getQueryParamString(router.query.hash);

const [ isLoading, setIsLoading ] = React.useState(true);
const countersQuery = useApiQuery('address_counters', {
pathParams: { hash: addressHash },
queryOptions: {
Expand All @@ -55,6 +55,8 @@ const AddressDetails = ({ addressQuery, scrollRef }: Props) => {
}
}).catch(err => {
return Promise.reject(err);
}).finally(() => {
setIsLoading(false);
});

const handleCounterItemClick = React.useCallback(() => {
Expand Down Expand Up @@ -99,6 +101,9 @@ const AddressDetails = ({ addressQuery, scrollRef }: Props) => {
return null;
}

if (isLoading) {
return <div>Loading...</div>;
}
return (
<Box>
<AddressHeadingInfo address={ data } token={ data.token } isLoading={ addressQuery.isPlaceholderData } isLinkDisabled/>
Expand Down
92 changes: 92 additions & 0 deletions ui/address/aspects/AddressAspectsHistory.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { Hide, Table, Tbody, Th, Tr } from '@chakra-ui/react';
import type { UseQueryResult } from '@tanstack/react-query';
import React from 'react';

import type { AddressAspectsHistoryResponse } from 'types/api/address';
import type { PaginationParams } from 'ui/shared/pagination/types';

import type { AspectType } from 'ui/address/AddressAspects';
import ActionBar from 'ui/shared/ActionBar';
import DataListDisplay from 'ui/shared/DataListDisplay';
import Pagination from 'ui/shared/pagination/Pagination';
import { default as Thead } from 'ui/shared/TheadSticky';

import AddressAspectsTableItem from './AddressAspectsTableItem';

interface Props {
query: UseQueryResult<AddressAspectsHistoryResponse> & {
pagination: PaginationParams;
};
aspectList: Array<Array<AspectType>>;
}

const AddressAspectsHistory = ({ query, aspectList }: Props) => {
const [ page, setPage ] = React.useState<number>(1);
const onNextPageClick =
React.useCallback(() => {
() => {
setPage(page => page + 1);
};
}, [ setPage ]);

const onPrevPageClick =
React.useCallback(() => {
() => {
setPage(page => page - 1);
};
}, [ setPage ]);

const resetPage =
React.useCallback(() => {
() => {
setPage(1);
};
}, [ setPage ]);

const content = query.data?.items ? (
<Hide below="lg" ssr={ false }>
<Table variant="simple" size="sm">
<Thead top={ query.pagination.isVisible ? 80 : 0 }>
<Tr>
<Th width="40%">Aspect ID</Th>
<Th width="20%">Join Points</Th>
<Th width="20%">Version</Th>
<Th width="20%">Priority</Th>
</Tr>
</Thead>
<Tbody>
{ aspectList[0] ?
aspectList[page - 1].map((item: AspectType, index: number) => (
<AddressAspectsTableItem
key={ index }
{ ...item }
page={ query.pagination.page }
isLoading={ query.isPlaceholderData }
/>
)) : '' }
</Tbody>
</Table>
</Hide>
) : null;

const actionBar = (
<ActionBar mt={ -6 }>
<Pagination ml="auto" page={ page } isVisible={ true } hasPages={ aspectList.length > 0 }
hasNextPage={ page < aspectList.length } canGoBackwards={ true } isLoading={ false }
onNextPageClick={ onNextPageClick } onPrevPageClick={ onPrevPageClick } resetPage={ resetPage }/>
</ActionBar>
);

return (
<DataListDisplay
mt={ 8 }
isError={ query.isError }
items={ aspectList }
emptyText="There is no aspect bound to this address."
content={ content }
actionBar={ actionBar }
/>
);
};

export default React.memo(AddressAspectsHistory);
39 changes: 39 additions & 0 deletions ui/address/aspects/AddressAspectsTableItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { Td, Tr, Skeleton } from '@chakra-ui/react';
import React from 'react';

import type { AspectType } from 'ui/address/AddressAspects';

type Props = AspectType & {
page: number;
isLoading: boolean;
};

const AddressAspectsTableItem = (props: Props) => {
return (
<Tr>
<Td>
<Skeleton isLoaded={ !props.isLoading } display="inline-block">
<span>{ props.aspectId }</span>
</Skeleton>
</Td>
<Td>
<Skeleton isLoaded={ !props.isLoading } color="text_secondary" display="inline-block">
<span>{ props.joinPoints ? Number(props.joinPoints) : '' }</span>
</Skeleton>
</Td>
<Td>
<Skeleton isLoaded={ !props.isLoading } color="text_secondary" display="inline-block">
<span>{ Number(props.version) }</span>
</Skeleton>
</Td>
<Td>
<Skeleton isLoaded={ !props.isLoading } color="text_secondary" display="inline-block">
<span>{ Number(props.priority) }</span>
</Skeleton>
</Td>

</Tr>
);
};

export default React.memo(AddressAspectsTableItem);
2 changes: 2 additions & 0 deletions ui/pages/Address.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import useContractTabs from 'lib/hooks/useContractTabs';
import useIsMobile from 'lib/hooks/useIsMobile';
import getQueryParamString from 'lib/router/getQueryParamString';
import { ADDRESS_INFO } from 'stubs/address';
import AddressAspects from 'ui/address/AddressAspects';
import AddressBlocksValidated from 'ui/address/AddressBlocksValidated';
import AddressCoinBalance from 'ui/address/AddressCoinBalance';
import AddressContract from 'ui/address/AddressContract';
Expand Down Expand Up @@ -89,6 +90,7 @@ const AddressPageContent = () => {
component: <AddressContract tabs={ contractTabs }/>,
subTabs: contractTabs.map(tab => tab.id),
} : undefined,
{ id: 'aspect', title: 'Aspects', component: <AddressAspects/> },
].filter(Boolean);
}, [ addressQuery.data, contractTabs ]);

Expand Down
4 changes: 2 additions & 2 deletions ui/snippets/header/Header.pw.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ test('no auth +@mobile', async({ mount, page }) => {
</TestApp>,
);

await expect(page).toHaveScreenshot({ clip: { x: 0, y: 0, width: 1500, height: 150 } });
await expect(page).toHaveScreenshot({ clip: { x: 0, y: 0, width: 1500, height: 150 }, maxDiffPixelRatio: 1 });
});

test.describe('dark mode', () => {
Expand All @@ -25,6 +25,6 @@ test.describe('dark mode', () => {
</TestApp>,
);

await expect(page).toHaveScreenshot({ clip: { x: 0, y: 0, width: 1500, height: 150 } });
await expect(page).toHaveScreenshot({ clip: { x: 0, y: 0, width: 1500, height: 150 }, maxDiffPixelRatio: 1 });
});
});
12 changes: 6 additions & 6 deletions ui/snippets/networkMenu/NetworkLogo.pw.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ base.describe('placeholder logo', () => {
</TestApp>,
);

await expect(component.locator('a')).toHaveScreenshot();
await expect(component.locator('a')).toHaveScreenshot({ maxDiffPixelRatio: 1 });
});

test.describe('screen xl', () => {
Expand All @@ -37,7 +37,7 @@ base.describe('placeholder logo', () => {
</TestApp>,
);

await expect(component.locator('a')).toHaveScreenshot();
await expect(component.locator('a')).toHaveScreenshot({ maxDiffPixelRatio: 1 });
});
});
});
Expand Down Expand Up @@ -77,14 +77,14 @@ base.describe('custom logo', () => {
});

test('+@dark-mode', async() => {
await expect(component.locator('a')).toHaveScreenshot();
await expect(component.locator('a')).toHaveScreenshot({ maxDiffPixelRatio: 1 });
});

test.describe('screen xl', () => {
test.use({ viewport: configs.viewport.xl });

test('+@dark-mode', async() => {
await expect(component.locator('a')).toHaveScreenshot();
await expect(component.locator('a')).toHaveScreenshot({ maxDiffPixelRatio: 1 });
});
});
});
Expand Down Expand Up @@ -126,14 +126,14 @@ base.describe('custom logo with dark option -@default +@dark-mode', () => {
});

test('', async() => {
await expect(component.locator('a')).toHaveScreenshot();
await expect(component.locator('a')).toHaveScreenshot({ maxDiffPixelRatio: 1 });
});

test.describe('screen xl', () => {
test.use({ viewport: configs.viewport.xl });

test('', async() => {
await expect(component.locator('a')).toHaveScreenshot();
await expect(component.locator('a')).toHaveScreenshot({ maxDiffPixelRatio: 1 });
});
});
});
8 changes: 4 additions & 4 deletions ui/snippets/networkMenu/NetworkMenu.pw.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,14 @@ extendedTest('base view +@dark-mode', async({ mount, page }) => {
</TestApp>,
);

await expect(page).toHaveScreenshot({ clip: { x: 0, y: 0, width: 36, height: 36 } });
await expect(page).toHaveScreenshot({ clip: { x: 0, y: 0, width: 36, height: 36 }, maxDiffPixelRatio: 1 });

await component.locator('button[aria-label="Network menu"]').hover();
await expect(page).toHaveScreenshot({ clip: { x: 0, y: 0, width: 36, height: 36 } });
await expect(page).toHaveScreenshot({ clip: { x: 0, y: 0, width: 36, height: 36 }, maxDiffPixelRatio: 1 });

await component.locator('button[aria-label="Network menu"]').click();
await expect(page).toHaveScreenshot({ clip: { x: 0, y: 0, width: 450, height: 550 } });
await expect(page).toHaveScreenshot({ clip: { x: 0, y: 0, width: 450, height: 550 }, maxDiffPixelRatio: 1 });

await component.getByText(/poa/i).hover();
await expect(page).toHaveScreenshot({ clip: { x: 0, y: 0, width: 450, height: 550 } });
await expect(page).toHaveScreenshot({ clip: { x: 0, y: 0, width: 450, height: 550 }, maxDiffPixelRatio: 1 });
});

0 comments on commit e203fed

Please sign in to comment.