Commit 513d4c35 authored by tom goriunov's avatar tom goriunov Committed by GitHub

Reorg badge and footer updates (#1263)

* [skip ci] fix envs validator

* Add tags to reorg blocks in search and quicksearch

Fixes #1131

* Change issue template when submitting issue from the footer

* donate button
parent 625eb0f2
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"> <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill="currentColor" d="M13.76 7.444h2.88a5.76 5.76 0 0 1 0 11.52v2.52c-3.6-1.44-8.64-3.6-8.64-8.28a5.76 5.76 0 0 1 5.76-5.76Zm1.44 10.08h1.44a4.32 4.32 0 1 0 0-8.64h-2.88a4.32 4.32 0 0 0-4.32 4.32c0 2.6 1.772 4.296 5.76 6.106v-1.786Z"/> <path fill-rule="evenodd" clip-rule="evenodd" d="M9.385 17.044c1.752 2.174 4.83 3.47 7.255 4.44v-2.52a5.76 5.76 0 0 0 0-11.52H16v2.281c.064.13.118.257.156.381L16 10.5v.5c.242-.242.259-.555.156-.894l.484-1.222a4.32 4.32 0 1 1 0 8.64H15.2v1.786c-1.654-.75-2.926-1.482-3.85-2.266H9.385Z" fill="currentColor"/>
<path fill="currentColor" d="M10.4 3.444H7.2a6.32 6.32 0 0 0-4.526 1.923A6.65 6.65 0 0 0 .8 10.008c0 1.741.674 3.41 1.874 4.642A6.32 6.32 0 0 0 7.2 16.572v2.872c4-1.64 9.6-4.102 9.6-9.436a6.65 6.65 0 0 0-1.875-4.641A6.32 6.32 0 0 0 10.4 3.444ZM8.8 14.931H7.2c-.63 0-1.255-.127-1.837-.374a4.793 4.793 0 0 1-1.557-1.068c-.446-.457-.8-1-1.04-1.597a5.033 5.033 0 0 1 0-3.768 4.933 4.933 0 0 1 1.04-1.597c.445-.457.975-.82 1.557-1.067A4.696 4.696 0 0 1 7.2 5.085h3.2a4.74 4.74 0 0 1 3.394 1.442 4.988 4.988 0 0 1 1.406 3.481c0 2.962-1.97 4.895-6.4 6.958v-2.035Z"/> <path fill-rule="evenodd" clip-rule="evenodd" d="M9.385 17.044c1.752 2.174 4.83 3.47 7.255 4.44v-2.52a5.76 5.76 0 0 0 0-11.52H16v2.281c.064.13.118.257.156.381L16 10.5v.5c.242-.242.259-.555.156-.894l.484-1.222a4.32 4.32 0 1 1 0 8.64H15.2v1.786c-1.654-.75-2.926-1.482-3.85-2.266H9.385Z" fill="currentColor"/>
<path d="M10.4 3.444H7.2a6.32 6.32 0 0 0-4.526 1.923A6.65 6.65 0 0 0 .8 10.008c0 1.741.674 3.41 1.874 4.642A6.32 6.32 0 0 0 7.2 16.572v2.872c4-1.64 9.6-4.102 9.6-9.436a6.65 6.65 0 0 0-1.875-4.641A6.32 6.32 0 0 0 10.4 3.444ZM8.8 14.931H7.2c-.63 0-1.255-.127-1.837-.374a4.793 4.793 0 0 1-1.557-1.068c-.446-.457-.8-1-1.04-1.597a5.033 5.033 0 0 1 0-3.768 4.933 4.933 0 0 1 1.04-1.597c.445-.457.975-.82 1.557-1.067A4.696 4.696 0 0 1 7.2 5.085h3.2a4.74 4.74 0 0 1 3.394 1.442 4.988 4.988 0 0 1 1.406 3.481c0 2.962-1.97 4.895-6.4 6.958v-2.035Z" fill="currentColor"/>
<path d="M10.4 3.444H7.2a6.32 6.32 0 0 0-4.526 1.923A6.65 6.65 0 0 0 .8 10.008c0 1.741.674 3.41 1.874 4.642A6.32 6.32 0 0 0 7.2 16.572v2.872c4-1.64 9.6-4.102 9.6-9.436a6.65 6.65 0 0 0-1.875-4.641A6.32 6.32 0 0 0 10.4 3.444ZM8.8 14.931H7.2c-.63 0-1.255-.127-1.837-.374a4.793 4.793 0 0 1-1.557-1.068c-.446-.457-.8-1-1.04-1.597a5.033 5.033 0 0 1 0-3.768 4.933 4.933 0 0 1 1.04-1.597c.445-.457.975-.82 1.557-1.067A4.696 4.696 0 0 1 7.2 5.085h3.2a4.74 4.74 0 0 1 3.394 1.442 4.988 4.988 0 0 1 1.406 3.481c0 2.962-1.97 4.895-6.4 6.958v-2.035Z" fill="currentColor"/>
</svg> </svg>
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M19.111 21H4.891a.674.674 0 0 1-.673-.674v-9.698a.674.674 0 0 1 .674-.674h14.22a.674.674 0 0 1 .673.674v9.698a.674.674 0 0 1-.674.674ZM5.566 19.652h12.871v-8.35H5.566v8.35Z" fill="currentColor"/>
<path d="M19.111 21H4.891a.674.674 0 0 1-.673-.674v-9.698a.674.674 0 0 1 .674-.674h14.22a.674.674 0 0 1 .673.674v9.698a.674.674 0 0 1-.674.674ZM5.566 19.652h12.871v-8.35H5.566v8.35Z" fill="currentColor"/>
<path d="M20.328 11.302H3.674A.674.674 0 0 1 3 10.628V7.006a.674.674 0 0 1 .674-.674h16.654a.674.674 0 0 1 .675.674v3.622a.674.674 0 0 1-.675.674ZM4.348 9.954h15.307V7.68H4.348v2.274Z" fill="currentColor"/>
<path d="M20.328 11.302H3.674A.674.674 0 0 1 3 10.628V7.006a.674.674 0 0 1 .674-.674h16.654a.674.674 0 0 1 .675.674v3.622a.674.674 0 0 1-.675.674ZM4.348 9.954h15.307V7.68H4.348v2.274Z" fill="currentColor"/>
<path d="M12 7.68a.674.674 0 0 1-.415-.144l-3.903-3.07a.55.55 0 0 0-.89.432v2.108a.674.674 0 1 1-1.348 0V4.898a1.898 1.898 0 0 1 3.071-1.491l3.902 3.07A.674.674 0 0 1 12 7.68Z" fill="currentColor"/>
<path d="M12 7.68a.674.674 0 0 1-.415-.144l-3.903-3.07a.55.55 0 0 0-.89.432v2.108a.674.674 0 1 1-1.348 0V4.898a1.898 1.898 0 0 1 3.071-1.491l3.902 3.07A.674.674 0 0 1 12 7.68Z" fill="currentColor"/>
<path d="M12.001 7.68a.674.674 0 0 1-.416-1.204l3.901-3.07a1.898 1.898 0 0 1 3.072 1.492v2.108a.674.674 0 1 1-1.348 0V4.898a.55.55 0 0 0-.89-.432l-3.902 3.07A.674.674 0 0 1 12 7.68Z" fill="currentColor"/>
<path d="M12.001 7.68a.674.674 0 0 1-.416-1.204l3.901-3.07a1.898 1.898 0 0 1 3.072 1.492v2.108a.674.674 0 1 1-1.348 0V4.898a.55.55 0 0 0-.89-.432l-3.902 3.07A.674.674 0 0 1 12 7.68Z" fill="currentColor"/>
</svg>
import React from 'react'; import React from 'react';
import config from 'configs/app'; import config from 'configs/app';
import isBrowser from 'lib/isBrowser';
const base = 'https://github.com/blockscout/blockscout/issues/new/';
const labels = 'new UI';
const title = `${ config.chain.name }: <Issue Title>`;
export default function useIssueUrl(backendVersion: string | undefined) { export default function useIssueUrl(backendVersion: string | undefined) {
const [ userAgent, setUserAgent ] = React.useState(''); const [ isLoading, setIsLoading ] = React.useState(true);
const isInBrowser = isBrowser();
React.useEffect(() => { React.useEffect(() => {
if (isInBrowser) { setIsLoading(false);
setUserAgent(window.navigator.userAgent); }, [ ]);
}
}, [ isInBrowser ]);
const body = React.useMemo(() => {
return `
*Describe your issue here.*
### Environment
* Backend Version/branch/commit: ${ backendVersion }
* Frontend Version+commit: ${ [ config.UI.footer.frontendVersion, config.UI.footer.frontendCommit ].filter(Boolean).join('+') }
* User Agent: ${ userAgent }
### Steps to reproduce return React.useMemo(() => {
if (isLoading) {
*Tell us how to reproduce this issue. ❤️ if you can push up a branch to your fork with a regression test we can run to reproduce locally.* return '';
}
### Expected behaviour
*Tell us what should happen.*
### Actual behaviour
*Tell us what happens instead.* const searchParams = new URLSearchParams({
`; template: 'bug_report.yml',
}, [ backendVersion, userAgent ]); labels: 'triage',
link: window.location.href,
'backend-version': backendVersion || '',
'frontend-version': [ config.UI.footer.frontendVersion, config.UI.footer.frontendCommit ].filter(Boolean).join('+'),
'additional-information': `**User Agent:** ${ window.navigator.userAgent }`,
});
return `https://github.com/blockscout/blockscout/issues/new/?${ searchParams.toString() }`;
}, [ backendVersion, isLoading ]);
const params = new URLSearchParams({ labels, title, body });
return base + '?' + params.toString();
} }
...@@ -38,6 +38,15 @@ export const block1: SearchResultBlock = { ...@@ -38,6 +38,15 @@ export const block1: SearchResultBlock = {
url: '/block/0x1af31d7535dded06bab9a88eb40ee2f8d0529a60ab3b8a7be2ba69b008cacbd1', url: '/block/0x1af31d7535dded06bab9a88eb40ee2f8d0529a60ab3b8a7be2ba69b008cacbd1',
}; };
export const block2: SearchResultBlock = {
block_hash: '0x1af31d7535dded06bab9a88eb40ee2f8d0529a60ab3b8a7be2ba69b008cacbd2',
block_number: 8198536,
block_type: 'reorg',
type: 'block' as const,
timestamp: '2022-12-11T18:55:20Z',
url: '/block/0x1af31d7535dded06bab9a88eb40ee2f8d0529a60ab3b8a7be2ba69b008cacbd2',
};
export const address1: SearchResultAddressOrContract = { export const address1: SearchResultAddressOrContract = {
address: '0xb64a30399f7F6b0C154c2E7Af0a3ec7B0A5b131a', address: '0xb64a30399f7F6b0C154c2E7Af0a3ec7B0A5b131a',
name: null, name: null,
......
...@@ -35,6 +35,7 @@ export interface SearchResultLabel { ...@@ -35,6 +35,7 @@ export interface SearchResultLabel {
export interface SearchResultBlock { export interface SearchResultBlock {
type: 'block'; type: 'block';
block_type?: 'block' | 'reorg';
block_number: number | string; block_number: number | string;
block_hash: string; block_hash: string;
timestamp: string; timestamp: string;
......
...@@ -101,6 +101,7 @@ test('search by block number +@mobile', async({ mount, page }) => { ...@@ -101,6 +101,7 @@ test('search by block number +@mobile', async({ mount, page }) => {
body: JSON.stringify({ body: JSON.stringify({
items: [ items: [
searchMock.block1, searchMock.block1,
searchMock.block2,
], ],
}), }),
})); }));
......
import { Flex, Grid, Icon, Image, Box, Text, Skeleton, useColorMode } from '@chakra-ui/react'; import { Flex, Grid, Icon, Image, Box, Text, Skeleton, useColorMode, Tag } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import xss from 'xss'; import xss from 'xss';
...@@ -174,6 +174,7 @@ const SearchResultListItem = ({ data, searchTerm, isLoading }: Props) => { ...@@ -174,6 +174,7 @@ const SearchResultListItem = ({ data, searchTerm, isLoading }: Props) => {
fontWeight={ 700 } fontWeight={ 700 }
/> />
</BlockEntity.Link> </BlockEntity.Link>
{ data.block_type === 'reorg' && <Tag ml={ 2 }>Reorg</Tag> }
</BlockEntity.Container> </BlockEntity.Container>
); );
} }
......
import { Tr, Td, Text, Flex, Icon, Image, Box, Skeleton, useColorMode } from '@chakra-ui/react'; import { Tr, Td, Text, Flex, Icon, Image, Box, Skeleton, useColorMode, Tag } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import xss from 'xss'; import xss from 'xss';
...@@ -263,9 +263,12 @@ const SearchResultTableItem = ({ data, searchTerm, isLoading }: Props) => { ...@@ -263,9 +263,12 @@ const SearchResultTableItem = ({ data, searchTerm, isLoading }: Props) => {
</BlockEntity.Container> </BlockEntity.Container>
</Td> </Td>
<Td fontSize="sm" verticalAlign="middle"> <Td fontSize="sm" verticalAlign="middle">
<Box overflow="hidden" whiteSpace="nowrap" as={ shouldHighlightHash ? 'mark' : 'span' } display="block"> <Flex columnGap={ 2 } alignItems="center">
<HashStringShortenDynamic hash={ data.block_hash }/> { data.block_type === 'reorg' && <Tag flexShrink={ 0 }>Reorg</Tag> }
</Box> <Box overflow="hidden" whiteSpace="nowrap" as={ shouldHighlightHash ? 'mark' : 'span' } display="block">
<HashStringShortenDynamic hash={ data.block_hash }/>
</Box>
</Flex>
</Td> </Td>
<Td fontSize="sm" verticalAlign="middle" isNumeric> <Td fontSize="sm" verticalAlign="middle" isNumeric>
<Text variant="secondary">{ dayjs(data.timestamp).format('llll') }</Text> <Text variant="secondary">{ dayjs(data.timestamp).format('llll') }</Text>
......
...@@ -6,6 +6,7 @@ import type { CustomLinksGroup } from 'types/footerLinks'; ...@@ -6,6 +6,7 @@ import type { CustomLinksGroup } from 'types/footerLinks';
import config from 'configs/app'; import config from 'configs/app';
import discussionsIcon from 'icons/discussions.svg'; import discussionsIcon from 'icons/discussions.svg';
import donateIcon from 'icons/donate.svg';
import editIcon from 'icons/edit.svg'; import editIcon from 'icons/edit.svg';
import cannyIcon from 'icons/social/canny.svg'; import cannyIcon from 'icons/social/canny.svg';
import discordIcon from 'icons/social/discord.svg'; import discordIcon from 'icons/social/discord.svg';
...@@ -73,6 +74,12 @@ const Footer = () => { ...@@ -73,6 +74,12 @@ const Footer = () => {
text: 'Discussions', text: 'Discussions',
url: 'https://github.com/orgs/blockscout/discussions', url: 'https://github.com/orgs/blockscout/discussions',
}, },
{
icon: donateIcon,
iconSize: '20px',
text: 'Donate',
url: 'https://github.com/sponsors/blockscout',
},
]; ];
const frontendLink = (() => { const frontendLink = (() => {
...@@ -142,7 +149,7 @@ const Footer = () => { ...@@ -142,7 +149,7 @@ const Footer = () => {
{ config.UI.footer.links && <Text fontWeight={ 500 } mb={ 3 }>Blockscout</Text> } { config.UI.footer.links && <Text fontWeight={ 500 } mb={ 3 }>Blockscout</Text> }
<Grid <Grid
gap={ 1 } gap={ 1 }
gridTemplateColumns={ config.UI.footer.links ? '160px' : { base: 'repeat(auto-fill, 160px)', lg: 'repeat(3, 160px)' } } gridTemplateColumns={ config.UI.footer.links ? '160px' : { base: 'repeat(auto-fill, 160px)', lg: 'repeat(4, 160px)' } }
gridTemplateRows={{ base: 'auto', lg: config.UI.footer.links ? 'auto' : 'repeat(2, auto)' }} gridTemplateRows={{ base: 'auto', lg: config.UI.footer.links ? 'auto' : 'repeat(2, auto)' }}
gridAutoFlow={{ base: 'row', lg: config.UI.footer.links ? 'row' : 'column' }} gridAutoFlow={{ base: 'row', lg: config.UI.footer.links ? 'row' : 'column' }}
mt={{ base: 0, lg: config.UI.footer.links ? 0 : '100px' }} mt={{ base: 0, lg: config.UI.footer.links ? 0 : '100px' }}
......
...@@ -149,6 +149,7 @@ test('search by block number +@mobile', async({ mount, page }) => { ...@@ -149,6 +149,7 @@ test('search by block number +@mobile', async({ mount, page }) => {
status: 200, status: 200,
body: JSON.stringify([ body: JSON.stringify([
searchMock.block1, searchMock.block1,
searchMock.block2,
]), ]),
})); }));
...@@ -160,7 +161,7 @@ test('search by block number +@mobile', async({ mount, page }) => { ...@@ -160,7 +161,7 @@ test('search by block number +@mobile', async({ mount, page }) => {
await page.getByPlaceholder(/search/i).type(String(searchMock.block1.block_number)); await page.getByPlaceholder(/search/i).type(String(searchMock.block1.block_number));
await page.waitForResponse(API_URL); await page.waitForResponse(API_URL);
await expect(page).toHaveScreenshot({ clip: { x: 0, y: 0, width: 1200, height: 300 } }); await expect(page).toHaveScreenshot({ clip: { x: 0, y: 0, width: 1200, height: 600 } });
}); });
test('search by block hash +@mobile', async({ mount, page }) => { test('search by block hash +@mobile', async({ mount, page }) => {
......
import { Text, Flex, Grid } from '@chakra-ui/react'; import { Text, Flex, Grid, Tag } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import type { SearchResultBlock } from 'types/api/search'; import type { SearchResultBlock } from 'types/api/search';
...@@ -46,6 +46,7 @@ const SearchBarSuggestBlock = ({ data, isMobile, searchTerm }: Props) => { ...@@ -46,6 +46,7 @@ const SearchBarSuggestBlock = ({ data, isMobile, searchTerm }: Props) => {
<Flex alignItems="center"> <Flex alignItems="center">
{ icon } { icon }
{ blockNumber } { blockNumber }
{ data.block_type === 'reorg' && <Tag ml="auto">Reorg</Tag> }
</Flex> </Flex>
{ hash } { hash }
<Text variant="secondary">{ date }</Text> <Text variant="secondary">{ date }</Text>
...@@ -59,7 +60,10 @@ const SearchBarSuggestBlock = ({ data, isMobile, searchTerm }: Props) => { ...@@ -59,7 +60,10 @@ const SearchBarSuggestBlock = ({ data, isMobile, searchTerm }: Props) => {
{ icon } { icon }
{ blockNumber } { blockNumber }
</Flex> </Flex>
{ hash } <Flex columnGap={ 3 } minW={ 0 }>
{ data.block_type === 'reorg' && <Tag flexShrink={ 0 }>Reorg</Tag> }
{ hash }
</Flex>
<Text variant="secondary" textAlign="end">{ date }</Text> <Text variant="secondary" textAlign="end">{ date }</Text>
</Grid> </Grid>
); );
......
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