Commit a2597538 authored by tom's avatar tom

Merge branch 'main' of github.com:tom2drum/block-scout into mobile-view-pages

parents 6a3398d7 32d9cf05
......@@ -27,7 +27,7 @@ export default function useNavItems() {
const accountNavItems = [
{ text: 'Watchlist', pathname: basePath + '/account/watchlist', icon: watchlistIcon },
{ text: 'Private tags', pathname: basePath + '/account/private_tags', icon: privateTagIcon },
{ text: 'Private tags', pathname: basePath + '/account/tag_address', icon: privateTagIcon },
{ text: 'Public tags', pathname: basePath + '/account/public_tags_request', icon: publicTagIcon },
{ text: 'API keys', pathname: basePath + '/account/api_key', icon: apiKeysIcon },
{ text: 'Custom ABI', pathname: basePath + '/account/custom_abi', icon: abiIcon },
......
......@@ -106,8 +106,12 @@ export const NETWORKS: Array<Network> = (() => {
// },
// ];
export const ACCOUNT_ROUTES = [ '/watchlist', '/private-tags', '/public-tags', '/api-keys', '/custom-abi' ];
export const ACCOUNT_ROUTES = [ '/watchlist', '/tag_address', '/tag_transaction', '/public_tags_request', '/api_key', '/custom_abi' ];
export function isAccountRoute(route: string) {
return ACCOUNT_ROUTES.includes(route);
}
export function getAvailablePaths() {
return NETWORKS.map(({ type, subType }) => ({ params: { network_type: type, network_sub_type: subType } }));
}
import type { NextPage } from 'next';
import type { NextPage, GetStaticPaths } from 'next';
import Head from 'next/head';
import React from 'react';
import { getAvailablePaths } from 'lib/networks';
import ApiKeys from 'ui/pages/ApiKeys';
const ApiKeysPage: NextPage = () => {
......@@ -14,3 +15,13 @@ const ApiKeysPage: NextPage = () => {
};
export default ApiKeysPage;
export const getStaticPaths: GetStaticPaths = async() => {
return { paths: getAvailablePaths(), fallback: false };
};
export const getStaticProps = async() => {
return {
props: {},
};
};
import type { NextPage } from 'next';
import type { NextPage, GetStaticPaths } from 'next';
import Head from 'next/head';
import React from 'react';
import { getAvailablePaths } from 'lib/networks';
import CustomAbi from 'ui/pages/CustomAbi';
const CustomAbiPage: NextPage = () => {
......@@ -14,3 +15,13 @@ const CustomAbiPage: NextPage = () => {
};
export default CustomAbiPage;
export const getStaticPaths: GetStaticPaths = async() => {
return { paths: getAvailablePaths(), fallback: false };
};
export const getStaticProps = async() => {
return {
props: {},
};
};
import type { NextPage } from 'next';
import Head from 'next/head';
import React, { useCallback, useState } from 'react';
import PrivateTags from 'ui/pages/PrivateTags';
const TABS = [ 'address', 'transaction' ];
const PrivateTagsPage: NextPage = () => {
const [ , setActiveTab ] = useState(TABS[0]);
const onChangeTab = useCallback((index: number) => {
setActiveTab(TABS[index]);
}, [ setActiveTab ]);
return (
<>
<Head><title>Private tags</title></Head>
<PrivateTags onChangeTab={ onChangeTab }/>
</>
);
};
export default PrivateTagsPage;
import type { NextPage } from 'next';
import type { NextPage, GetStaticPaths } from 'next';
import Head from 'next/head';
import React from 'react';
import { getAvailablePaths } from 'lib/networks';
import PublicTags from 'ui/pages/PublicTags';
const PublicTagsPage: NextPage = () => {
......@@ -14,3 +15,13 @@ const PublicTagsPage: NextPage = () => {
};
export default PublicTagsPage;
export const getStaticPaths: GetStaticPaths = async() => {
return { paths: getAvailablePaths(), fallback: false };
};
export const getStaticProps = async() => {
return {
props: {},
};
};
import type { NextPage, GetStaticPaths } from 'next';
import Head from 'next/head';
import React from 'react';
import { getAvailablePaths } from 'lib/networks';
import PrivateTags from 'ui/pages/PrivateTags';
const AddressTagsPage: NextPage = () => {
return (
<>
<Head><title>Public tags</title></Head>
<PrivateTags tab="address"/>
</>
);
};
export default AddressTagsPage;
export const getStaticPaths: GetStaticPaths = async() => {
return { paths: getAvailablePaths(), fallback: false };
};
export const getStaticProps = async() => {
return {
props: {},
};
};
import type { NextPage, GetStaticPaths } from 'next';
import Head from 'next/head';
import React from 'react';
import { getAvailablePaths } from 'lib/networks';
import PrivateTags from 'ui/pages/PrivateTags';
const TransactionTagsPage: NextPage = () => {
return (
<>
<Head><title>Public tags</title></Head>
<PrivateTags tab="transaction"/>
</>
);
};
export default TransactionTagsPage;
export const getStaticPaths: GetStaticPaths = async() => {
return { paths: getAvailablePaths(), fallback: false };
};
export const getStaticProps = async() => {
return {
props: {},
};
};
import type { NextPage } from 'next';
import type { NextPage, GetStaticPaths } from 'next';
import Head from 'next/head';
import React from 'react';
import { getAvailablePaths } from 'lib/networks';
import WatchList from 'ui/pages/Watchlist';
const WatchListPage: NextPage = () => {
......@@ -14,3 +15,13 @@ const WatchListPage: NextPage = () => {
};
export default WatchListPage;
export const getStaticPaths: GetStaticPaths = async() => {
return { paths: getAvailablePaths(), fallback: false };
};
export const getStaticProps = async() => {
return {
props: {},
};
};
import type { NextPage } from 'next';
import type { NextPage, GetStaticPaths } from 'next';
import Head from 'next/head';
import React from 'react';
import { getAvailablePaths } from 'lib/networks';
import MyProfile from 'ui/pages/MyProfile';
const MyProfilePage: NextPage = () => {
......@@ -14,3 +15,13 @@ const MyProfilePage: NextPage = () => {
};
export default MyProfilePage;
export const getStaticPaths: GetStaticPaths = async() => {
return { paths: getAvailablePaths(), fallback: false };
};
export const getStaticProps = async() => {
return {
props: {},
};
};
import { Center, VStack, Box } from '@chakra-ui/react';
import type { NextPage } from 'next';
import type { NextPage, GetStaticPaths } from 'next';
import { useRouter } from 'next/router';
import React from 'react';
import { getAvailablePaths } from 'lib/networks';
import Page from 'ui/shared/Page/Page';
const Home: NextPage = () => {
......@@ -22,3 +23,13 @@ const Home: NextPage = () => {
};
export default Home;
export const getStaticPaths: GetStaticPaths = async() => {
return { paths: getAvailablePaths(), fallback: false };
};
export const getStaticProps = async() => {
return {
props: {},
};
};
......@@ -92,7 +92,7 @@ const ApiKeyForm: React.FC<Props> = ({ data, onClose, setAlertVisible }) => {
const renderTokenInput = useCallback(({ field }: {field: ControllerRenderProps<Inputs, 'token'>}) => {
return (
<FormControl variant="floating" id="address" isRequired>
<FormControl variant="floating" id="address">
<Input
{ ...field }
disabled={ true }
......@@ -134,6 +134,7 @@ const ApiKeyForm: React.FC<Props> = ({ data, onClose, setAlertVisible }) => {
control={ control }
rules={{
maxLength: NAME_MAX_LENGTH,
required: true,
}}
render={ renderNameInput }
/>
......
......@@ -142,7 +142,10 @@ const CustomAbiForm: React.FC<Props> = ({ data, onClose, setAlertVisible }) => {
name="contract_address_hash"
control={ control }
render={ renderContractAddressInput }
rules={{ pattern: ADDRESS_REGEXP }}
rules={{
pattern: ADDRESS_REGEXP,
required: true,
}}
/>
</Box>
<Box marginTop={ 5 }>
......@@ -150,6 +153,7 @@ const CustomAbiForm: React.FC<Props> = ({ data, onClose, setAlertVisible }) => {
name="name"
control={ control }
render={ renderNameInput }
rules={{ required: true }}
/>
</Box>
<Box marginTop={ 5 }>
......@@ -157,6 +161,7 @@ const CustomAbiForm: React.FC<Props> = ({ data, onClose, setAlertVisible }) => {
name="abi"
control={ control }
render={ renderAbiInput }
rules={{ required: true }}
/>
</Box>
<Box marginTop={ 8 }>
......
......@@ -6,27 +6,38 @@ import {
TabPanel,
TabPanels,
} from '@chakra-ui/react';
import React, { useCallback } from 'react';
import React, { useCallback, useState } from 'react';
import useBasePath from 'lib/hooks/useBasePath';
import PrivateAddressTags from 'ui/privateTags/PrivateAddressTags';
import PrivateTransactionTags from 'ui/privateTags/PrivateTransactionTags';
import AccountPageHeader from 'ui/shared/AccountPageHeader';
import Page from 'ui/shared/Page/Page';
const TABS = [ 'address', 'transaction' ] as const;
type TabName = typeof TABS[number];
type Props = {
onChangeTab: (index: number) => void;
tab: TabName;
}
const PrivateTags = ({ onChangeTab: onChangeTabProps }: Props) => {
const onTabChange = useCallback((index: number) => {
onChangeTabProps(index);
}, [ onChangeTabProps ]);
const PrivateTags = ({ tab }: Props) => {
const [ , setActiveTab ] = useState<TabName>(tab);
const basePath = useBasePath();
const onChangeTab = useCallback((index: number) => {
setActiveTab(TABS[index]);
const newUrl = basePath + '/account/' + (TABS[index] === 'address' ? 'tag_address' : 'tag_transaction');
history.replaceState(history.state, '', newUrl);
}, [ setActiveTab, basePath ]);
return (
<Page>
<Box h="100%">
<AccountPageHeader text="Private tags"/>
<Tabs variant="soft-rounded" colorScheme="blue" isLazy onChange={ onTabChange }>
<Tabs variant="soft-rounded" colorScheme="blue" isLazy onChange={ onChangeTab } defaultIndex={ TABS.indexOf(tab) }>
<TabList marginBottom={{ base: 6, lg: 8 }}>
<Tab>Address</Tab>
<Tab>Transaction</Tab>
......
......@@ -98,6 +98,7 @@ const AddressForm: React.FC<Props> = ({ data, onClose, setAlertVisible }) => {
control={ control }
rules={{
pattern: ADDRESS_REGEXP,
required: true,
}}
render={ renderAddressInput }
/>
......@@ -108,6 +109,7 @@ const AddressForm: React.FC<Props> = ({ data, onClose, setAlertVisible }) => {
control={ control }
rules={{
maxLength: TAG_MAX_LENGTH,
required: true,
}}
render={ renderTagInput }
/>
......
......@@ -97,6 +97,7 @@ const TransactionForm: React.FC<Props> = ({ data, onClose, setAlertVisible }) =>
control={ control }
rules={{
pattern: TRANSACTION_HASH_REGEXP,
required: true,
}}
render={ renderTransactionInput }
/>
......@@ -107,6 +108,7 @@ const TransactionForm: React.FC<Props> = ({ data, onClose, setAlertVisible }) =>
control={ control }
rules={{
maxLength: TAG_MAX_LENGTH,
required: true,
}}
render={ renderTagInput }
/>
......
......@@ -40,7 +40,10 @@ export default function PublicTagFormAction({ control, index, fieldsLength, erro
name={ `addresses.${ index }.address` }
control={ control }
render={ renderAddressInput }
rules={{ pattern: ADDRESS_REGEXP }}
rules={{
pattern: ADDRESS_REGEXP,
required: index === 0,
}}
/>
<Flex
columnGap={ 5 }
......
......@@ -36,7 +36,10 @@ export default function PublicTagFormComment({ control, error, size }: Props) {
name="comment"
control={ control }
render={ renderComment }
rules={{ maxLength: TEXT_INPUT_MAX_LENGTH }}
rules={{
maxLength: TEXT_INPUT_MAX_LENGTH,
required: true,
}}
/>
);
}
......@@ -133,7 +133,7 @@ const PublicTagsForm = ({ changeToDataScreen, data }: Props) => {
e.error?.full_name && setError('fullName', { type: 'custom', message: getErrorMessage(e.error, 'full_name') });
e.error?.email && setError('email', { type: 'custom', message: getErrorMessage(e.error, 'email') });
e.error?.tags && setError('tags', { type: 'custom', message: getErrorMessage(e.error, 'tags') });
e.error?.addresses && setError('addresses.0', { type: 'custom', message: getErrorMessage(e.error, 'addresses') });
e.error?.addresses && setError('addresses.0.address', { type: 'custom', message: getErrorMessage(e.error, 'addresses') });
e.error?.additional_comment && setError('comment', { type: 'custom', message: getErrorMessage(e.error, 'additional_comment') });
} else {
setAlertVisible(true);
......@@ -215,7 +215,7 @@ const PublicTagsForm = ({ changeToDataScreen, data }: Props) => {
<Box position="relative" key={ field.id } marginBottom={ 4 }>
<PublicTagFormAddressInput
control={ control }
error={ errors?.addresses?.[index] as FieldError }
error={ errors?.addresses?.[index]?.address as FieldError }
index={ index }
fieldsLength={ fields.length }
onAddFieldClick={ onAddFieldClick }
......
......@@ -45,7 +45,7 @@ export default function PublicTagsFormInput<Inputs extends FieldValues>({
name={ fieldName }
control={ control }
render={ renderInput }
rules={{ pattern }}
rules={{ pattern, required }}
/>
);
}
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