Commit 2e6bd017 authored by tom's avatar tom

Merge branch 'main' of github.com:blockscout/frontend into internal-link

parents 3653f540 96ddfc0c
......@@ -6,7 +6,7 @@ export default async function insertAdPlaceholder(page: Page) {
const adContainer = document.getElementById('adBanner');
const adReplacer = document.createElement('div');
adReplacer.style.width = '200px';
adReplacer.style.height = '100px';
adReplacer.style.height = '100%';
adReplacer.style.background = '#f00';
adContainer?.replaceChildren(adReplacer);
});
......
......@@ -75,10 +75,10 @@ const AddressBlocksValidated = ({ scrollRef }: Props) => {
if (query.isLoading) {
return (
<>
<Hide below="lg">
<Hide below="lg" ssr={ false }>
<SkeletonTable columns={ [ '17%', '17%', '16%', '25%', '25%' ] }/>
</Hide>
<Show below="lg">
<Show below="lg" ssr={ false }>
<SkeletonList/>
</Show>
</>
......@@ -95,7 +95,7 @@ const AddressBlocksValidated = ({ scrollRef }: Props) => {
return (
<>
<Hide below="lg">
<Hide below="lg" ssr={ false }>
<Table variant="simple" size="sm">
<Thead top={ 80 }>
<Tr>
......@@ -113,7 +113,7 @@ const AddressBlocksValidated = ({ scrollRef }: Props) => {
</Tbody>
</Table>
</Hide>
<Show below="lg">
<Show below="lg" ssr={ false }>
{ query.data.items.map((item) => (
<AddressBlocksValidatedListItem key={ item.height } { ...item } page={ query.pagination.page }/>
)) }
......
......@@ -48,8 +48,8 @@ const AddressInternalTxs = ({ scrollRef }: {scrollRef?: React.RefObject<HTMLDivE
if (isLoading) {
return (
<>
<Show below="lg"><AddressIntTxsSkeletonMobile/></Show>
<Hide below="lg"><AddressIntTxsSkeletonDesktop/></Hide>
<Show below="lg" ssr={ false }><AddressIntTxsSkeletonMobile/></Show>
<Hide below="lg" ssr={ false }><AddressIntTxsSkeletonDesktop/></Hide>
</>
);
}
......
......@@ -166,10 +166,10 @@ const AddressTokenTransfers = ({ scrollRef }: {scrollRef?: React.RefObject<HTMLD
if (isLoading) {
return (
<>
<Hide below="lg">
<Hide below="lg" ssr={ false }>
<SkeletonTable columns={ [ '44px', '185px', '160px', '25%', '25%', '25%', '25%' ] }/>
</Hide>
<Show below="lg">
<Show below="lg" ssr={ false }>
<SkeletonList/>
</Show>
</>
......@@ -191,7 +191,7 @@ const AddressTokenTransfers = ({ scrollRef }: {scrollRef?: React.RefObject<HTMLD
const items = data.items.reduce(flattenTotal, []);
return (
<>
<Hide below="lg">
<Hide below="lg" ssr={ false }>
<TokenTransferTable
data={ items }
baseAddress={ currentAddress }
......@@ -203,7 +203,7 @@ const AddressTokenTransfers = ({ scrollRef }: {scrollRef?: React.RefObject<HTMLD
socketInfoNum={ newItemsCount }
/>
</Hide>
<Show below="lg">
<Show below="lg" ssr={ false }>
{ pagination.page === 1 && !tokenFilter && (
<SocketNewItemsNotice
url={ window.location.href }
......
......@@ -29,10 +29,10 @@ const AddressCoinBalanceHistory = ({ query }: Props) => {
if (query.isLoading) {
return (
<>
<Hide below="lg">
<Hide below="lg" ssr={ false }>
<SkeletonTable columns={ [ '25%', '25%', '25%', '25%', '120px' ] }/>
</Hide>
<Show below="lg">
<Show below="lg" ssr={ false }>
<SkeletonList/>
</Show>
</>
......@@ -45,7 +45,7 @@ const AddressCoinBalanceHistory = ({ query }: Props) => {
return (
<>
<Hide below="lg">
<Hide below="lg" ssr={ false }>
<Table variant="simple" size="sm">
<Thead top={ 80 }>
<Tr>
......@@ -63,7 +63,7 @@ const AddressCoinBalanceHistory = ({ query }: Props) => {
</Tbody>
</Table>
</Hide>
<Show below="lg">
<Show below="lg" ssr={ false }>
{ query.data.items.map((item) => (
<AddressCoinBalanceListItem key={ item.block_number } { ...item } page={ query.pagination.page }/>
)) }
......
......@@ -33,7 +33,7 @@ type Inputs = {
const NAME_MAX_LENGTH = 255;
const ApiKeyForm: React.FC<Props> = ({ data, onClose, setAlertVisible }) => {
const { control, handleSubmit, formState: { errors, isValid, isDirty }, setError } = useForm<Inputs>({
const { control, handleSubmit, formState: { errors, isDirty }, setError } = useForm<Inputs>({
mode: 'onTouched',
defaultValues: {
token: data?.api_key || '',
......@@ -147,7 +147,7 @@ const ApiKeyForm: React.FC<Props> = ({ data, onClose, setAlertVisible }) => {
<Button
size="lg"
type="submit"
disabled={ !isValid || !isDirty }
disabled={ !isDirty }
isLoading={ mutation.isLoading }
>
{ data ? 'Save' : 'Generate API key' }
......
......@@ -36,7 +36,7 @@ type Inputs = {
const NAME_MAX_LENGTH = 255;
const CustomAbiForm: React.FC<Props> = ({ data, onClose, setAlertVisible }) => {
const { control, formState: { errors, isValid, isDirty }, handleSubmit, setError } = useForm<Inputs>({
const { control, formState: { errors, isDirty }, handleSubmit, setError } = useForm<Inputs>({
defaultValues: {
contract_address_hash: data?.contract_address_hash || '',
name: data?.name || '',
......@@ -174,7 +174,7 @@ const CustomAbiForm: React.FC<Props> = ({ data, onClose, setAlertVisible }) => {
<Button
size="lg"
type="submit"
disabled={ !isValid || !isDirty }
disabled={ !isDirty }
isLoading={ mutation.isLoading }
>
{ data ? 'Save' : 'Create custom ABI' }
......
......@@ -34,12 +34,8 @@ const Accounts = () => {
return (
<>
{ bar }
<Show below="lg">
<SkeletonList/>
</Show>
<Hide below="lg">
<SkeletonTable columns={ [ '64px', '30%', '20%', '20%', '15%', '15%' ] }/>
</Hide>
<SkeletonList display={{ base: 'block', lg: 'none' }}/>
<SkeletonTable display={{ base: 'none', lg: 'block' }} columns={ [ '64px', '30%', '20%', '20%', '15%', '15%' ] }/>
</>
);
}
......
......@@ -21,6 +21,7 @@ import AddressTxs from 'ui/address/AddressTxs';
import ContractCode from 'ui/address/contract/ContractCode';
import ContractRead from 'ui/address/contract/ContractRead';
import ContractWrite from 'ui/address/contract/ContractWrite';
import AdBanner from 'ui/shared/ad/AdBanner';
import TextAd from 'ui/shared/ad/TextAd';
import Page from 'ui/shared/Page/Page';
import PageTitle from 'ui/shared/Page/PageTitle';
......@@ -134,6 +135,7 @@ const AddressPageContent = () => {
/>
) }
<AddressDetails addressQuery={ addressQuery } scrollRef={ tabsScrollRef }/>
<AdBanner mt={{ base: 6, lg: 8 }} justifyContent="center"/>
{ /* should stay before tabs to scroll up whith pagination */ }
<Box ref={ tabsScrollRef }></Box>
{ addressQuery.isLoading ? <SkeletonTabs/> : content }
......
......@@ -32,10 +32,10 @@ const SearchResultsPageContent = () => {
if (isLoading) {
return (
<Box>
<Show below="lg">
<Show below="lg" ssr={ false }>
<SkeletonList/>
</Show>
<Hide below="lg">
<Hide below="lg" ssr={ false }>
<SkeletonTable columns={ [ '50%', '50%', '150px' ] }/>
</Hide>
</Box>
......
......@@ -5,6 +5,7 @@ import { token as contract } from 'mocks/address/address';
import { tokenInfo, tokenCounters } from 'mocks/tokens/tokenInfo';
import TestApp from 'playwright/TestApp';
import buildApiUrl from 'playwright/utils/buildApiUrl';
import insertAdPlaceholder from 'playwright/utils/insertAdPlaceholder';
import Token from './Token';
......@@ -51,5 +52,7 @@ test('base view +@dark-mode', async({ mount, page }) => {
{ hooksConfig },
);
await insertAdPlaceholder(page);
await expect(component.locator('main')).toHaveScreenshot();
});
......@@ -8,6 +8,7 @@ import useApiQuery from 'lib/api/useApiQuery';
import { useAppContext } from 'lib/appContext';
import useIsMobile from 'lib/hooks/useIsMobile';
import useQueryWithPages from 'lib/hooks/useQueryWithPages';
import AdBanner from 'ui/shared/ad/AdBanner';
import TextAd from 'ui/shared/ad/TextAd';
import Page from 'ui/shared/Page/Page';
import PageTitle from 'ui/shared/Page/PageTitle';
......@@ -109,7 +110,7 @@ const TokenPageContent = () => {
) }
<TokenContractInfo tokenQuery={ tokenQuery }/>
<TokenDetails tokenQuery={ tokenQuery }/>
<AdBanner mt={{ base: 6, lg: 8 }} justifyContent="center"/>
{ /* should stay before tabs to scroll up whith pagination */ }
<Box ref={ scrollRef }></Box>
......
......@@ -34,7 +34,7 @@ type Inputs = {
const AddressForm: React.FC<Props> = ({ data, onClose, setAlertVisible }) => {
const apiFetch = useApiFetch();
const [ pending, setPending ] = useState(false);
const { control, handleSubmit, formState: { errors, isValid, isDirty }, setError } = useForm<Inputs>({
const { control, handleSubmit, formState: { errors, isDirty }, setError } = useForm<Inputs>({
mode: 'onTouched',
defaultValues: {
address: data?.address_hash || '',
......@@ -124,7 +124,7 @@ const AddressForm: React.FC<Props> = ({ data, onClose, setAlertVisible }) => {
<Button
size="lg"
type="submit"
disabled={ !isValid || !isDirty }
disabled={ !isDirty }
isLoading={ pending }
>
{ data ? 'Save changes' : 'Add tag' }
......
......@@ -35,7 +35,7 @@ const TransactionForm: React.FC<Props> = ({ data, onClose, setAlertVisible }) =>
const [ pending, setPending ] = useState(false);
const formBackgroundColor = useColorModeValue('white', 'gray.900');
const { control, handleSubmit, formState: { errors, isValid, isDirty }, setError } = useForm<Inputs>({
const { control, handleSubmit, formState: { errors, isDirty }, setError } = useForm<Inputs>({
mode: 'onTouched',
defaultValues: {
transaction: data?.transaction_hash || '',
......@@ -123,7 +123,7 @@ const TransactionForm: React.FC<Props> = ({ data, onClose, setAlertVisible }) =>
<Button
size="lg"
type="submit"
disabled={ !isValid || !isDirty }
disabled={ !isDirty }
isLoading={ pending }
>
{ data ? 'Save changes' : 'Add tag' }
......
......@@ -61,7 +61,7 @@ const PublicTagsForm = ({ changeToDataScreen, data }: Props) => {
const apiFetch = useApiFetch();
const inputSize = { base: 'md', lg: 'lg' };
const { control, handleSubmit, formState: { errors, isValid, isDirty }, setError } = useForm<Inputs>({
const { control, handleSubmit, formState: { errors, isDirty }, setError } = useForm<Inputs>({
defaultValues: {
fullName: data?.full_name || '',
email: data?.email || '',
......@@ -236,7 +236,7 @@ const PublicTagsForm = ({ changeToDataScreen, data }: Props) => {
<Button
size="lg"
type="submit"
disabled={ !isValid || !isDirty }
disabled={ !isDirty }
isLoading={ mutation.isLoading }
>
Send request
......
......@@ -22,7 +22,7 @@ var AdButler = AdButler || {}; AdButler.ads = AdButler.ads || [];
const AdbutlerBanner = ({ className }: { className?: string }) => {
return (
<Flex className={ className } id="adBanner">
<Flex className={ className } id="adBanner" h={{ base: '100px', lg: '90px' }}>
<div id="ad-banner"></div>
<Script id="ad-butler-1">{ scriptText1 }</Script>
<Script id="ad-butler-2">{ scriptText2 }</Script>
......
......@@ -32,7 +32,7 @@ const CoinzillaBanner = ({ className }: { className?: string }) => {
}, [ isInBrowser ]);
return (
<Flex className={ className } id="adBanner">
<Flex className={ className } id="adBanner" h={{ base: '100px', lg: '90px' }}>
<Script src="https://coinzillatag.com/lib/display.js"/>
<div className="coinzilla" data-zone="C-26660bf627543e46851"></div>
</Flex>
......
import { Box, Flex, Skeleton, SkeletonCircle } from '@chakra-ui/react';
import { Box, Flex, Skeleton, SkeletonCircle, chakra } from '@chakra-ui/react';
import React from 'react';
const SkeletonList = () => {
const SkeletonList = ({ className }: {className?: string}) => {
return (
<Box>
<Box className={ className }>
{ Array.from(Array(2)).map((item, index) => (
<Flex
key={ index }
......@@ -35,4 +35,4 @@ const SkeletonList = () => {
);
};
export default SkeletonList;
export default chakra(SkeletonList);
import { HStack, Skeleton } from '@chakra-ui/react';
import { Box, HStack, Skeleton, chakra } from '@chakra-ui/react';
import React from 'react';
interface Props {
columns: Array<string>;
className?: string;
}
const SkeletonTable = ({ columns }: Props) => {
const SkeletonTable = ({ columns, className }: Props) => {
return (
<div>
<Box className={ className }>
<Skeleton height={ 10 } width="100%" borderBottomLeftRadius="none" borderBottomRightRadius="none"/>
{ Array.from(Array(3)).map((item, index) => (
<HStack key={ index } spacing={ 6 } marginTop={ 8 }>
......@@ -22,8 +23,8 @@ const SkeletonTable = ({ columns }: Props) => {
)) }
</HStack>
)) }
</div>
</Box>
);
};
export default React.memo(SkeletonTable);
export default React.memo(chakra(SkeletonTable));
......@@ -66,11 +66,11 @@ const TokenTransfer = ({ transfersQuery, token }: Props) => {
if (isLoading) {
return (
<>
<Hide below="lg">
<Hide below="lg" ssr={ false }>
<SkeletonTable columns={ [ '45%', '15%', '36px', '15%', '25%' ] }
/>
</Hide>
<Show below="lg">
<Show below="lg" ssr={ false }>
<SkeletonList/>
</Show>
</>
......@@ -88,7 +88,7 @@ const TokenTransfer = ({ transfersQuery, token }: Props) => {
const items = data.items.reduce(flattenTotal, []);
return (
<>
<Hide below="lg">
<Hide below="lg" ssr={ false }>
<TokenTransferTable
data={ items }
top={ 80 }
......@@ -100,7 +100,7 @@ const TokenTransfer = ({ transfersQuery, token }: Props) => {
socketInfoNum={ newItemsCount }
/>
</Hide>
<Show below="lg">
<Show below="lg" ssr={ false }>
{ pagination.page === 1 && (
<SocketNewItemsNotice
url={ window.location.href }
......
......@@ -69,19 +69,15 @@ const Tokens = () => {
const bar = (
<>
<Show below="lg">
<HStack spacing={ 3 } mb={ 6 }>
<HStack spacing={ 3 } mb={ 6 } display={{ base: 'flex', lg: 'none' }}>
{ typeFilter }
{ filterInput }
</HStack>
<ActionBar mt={ -6 }>
<HStack spacing={ 3 } display={{ base: 'none', lg: 'flex' }}>
{ typeFilter }
{ filterInput }
</HStack>
</Show>
<ActionBar mt={ -6 }>
<Hide below="lg">
<HStack spacing={ 3 }>
{ typeFilter }
{ filterInput }
</HStack>
</Hide>
{ isPaginationVisible && <Pagination ml="auto" { ...pagination }/> }
</ActionBar>
</>
......@@ -91,10 +87,8 @@ const Tokens = () => {
return (
<>
{ bar }
<Show below="lg"><SkeletonList/></Show>
<Hide below="lg">
<SkeletonTable columns={ [ '25px', '33%', '33%', '33%', '110px' ] }/>
</Hide>
<SkeletonList display={{ base: 'block', lg: 'none' }}/>
<SkeletonTable display={{ base: 'none', lg: 'block' }} columns={ [ '25px', '33%', '33%', '33%', '110px' ] }/>
</>
);
}
......
......@@ -101,8 +101,8 @@ const TxInternals = () => {
if (isLoading || txInfo.isLoading) {
return (
<>
<Show below="lg"><SkeletonList/></Show>
<Hide below="lg"><SkeletonTable columns={ [ '28%', '20%', '24px', '20%', '16%', '16%' ] }/></Hide>
<Show below="lg" ssr={ false }><SkeletonList/></Show>
<Hide below="lg" ssr={ false }><SkeletonTable columns={ [ '28%', '20%', '24px', '20%', '16%', '16%' ] }/></Hide>
</>
);
}
......
......@@ -83,10 +83,10 @@ const TxTokenTransfer = () => {
const items = tokenTransferQuery.data.items.reduce(flattenTotal, []);
return (
<>
<Hide below="lg">
<Hide below="lg" ssr={ false }>
<TokenTransferTable data={ items } top={ 80 }/>
</Hide>
<Show below="lg">
<Show below="lg" ssr={ false }>
<TokenTransferList data={ items }/>
</Show>
</>
......
......@@ -15,13 +15,14 @@ const TxDetailsSkeleton = () => {
);
return (
<Grid columnGap={ 8 } rowGap={{ base: 5, lg: 7 }} templateColumns={{ base: '1fr', lg: '210px 1fr' }} maxW="1000px">
<Grid columnGap={ 8 } rowGap={{ base: 5, lg: 7 }} templateColumns={{ base: '1fr', lg: '210px 1fr' }} maxW="1000px" pt={{ base: 1, lg: 2 }}>
<DetailsSkeletonRow/>
<DetailsSkeletonRow w="20%"/>
<DetailsSkeletonRow w="50%"/>
<DetailsSkeletonRow/>
<DetailsSkeletonRow w="70%"/>
<DetailsSkeletonRow w="70%"/>
<GridItem h={{ base: '82px', lg: '38px' }}/>
{ sectionGap }
<DetailsSkeletonRow w="40%"/>
<DetailsSkeletonRow w="40%"/>
......
......@@ -61,7 +61,7 @@ const TxDetailsTokenTransfers = ({ data, txHash }: Props) => {
}) }
{ showViewAllLink && (
<>
<Show above="lg"><GridItem></GridItem></Show>
<Show above="lg" ssr={ false }><GridItem></GridItem></Show>
<GridItem fontSize="sm" alignItems="center" display="inline-flex" pl={{ base: '28px', lg: 0 }}>
<Icon as={ tokenIcon } boxSize={ 6 }/>
<LinkInternal href={ viewAllUrl }>
......
......@@ -73,7 +73,7 @@ const AddressForm: React.FC<Props> = ({ data, onSuccess, setAlertVisible, isAdd
notificationsDefault = data.notification_settings;
}
const { control, handleSubmit, formState: { errors, isValid, isDirty }, setError } = useForm<Inputs>({
const { control, handleSubmit, formState: { errors, isDirty }, setError } = useForm<Inputs>({
defaultValues: {
address: data?.address_hash || '',
tag: data?.name || '',
......@@ -192,7 +192,7 @@ const AddressForm: React.FC<Props> = ({ data, onSuccess, setAlertVisible, isAdd
size="lg"
type="submit"
isLoading={ pending }
disabled={ !isValid || !isDirty }
disabled={ !isDirty }
>
{ !isAdd ? 'Save changes' : 'Add address' }
</Button>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment