diff --git a/CHANGELOG.md b/CHANGELOG.md index c6a860e30..fff2f0e52 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -94,6 +94,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Improvements +- [#843](https://github.com/alleslabs/celatone-frontend/pull/843) Add link to user document - [#845](https://github.com/alleslabs/celatone-frontend/pull/845) Edit error fetching message on the contract state - [#844](https://github.com/alleslabs/celatone-frontend/pull/844) Modify wording status for rejected proposals - [#841](https://github.com/alleslabs/celatone-frontend/pull/841) Bump cosmos-kit package fixing the installed wallet issue diff --git a/src/lib/components/PageHeader.tsx b/src/lib/components/PageHeader.tsx new file mode 100644 index 000000000..a60cc82e4 --- /dev/null +++ b/src/lib/components/PageHeader.tsx @@ -0,0 +1,37 @@ +import { Flex, Heading, Text } from "@chakra-ui/react"; + +import { useMobile } from "lib/app-provider"; + +import { UserDocsLink } from "./UserDocsLink"; + +interface PageHeaderProps { + title: string; + subtitle: string; + docHref: string; +} + +export const PageHeader = ({ title, subtitle, docHref }: PageHeaderProps) => { + const isMobile = useMobile(); + return ( + +
+ + + {title} + + {isMobile && } + + + {subtitle} + +
+ {!isMobile && } +
+ ); +}; diff --git a/src/lib/components/UserDocsLink.tsx b/src/lib/components/UserDocsLink.tsx new file mode 100644 index 000000000..42543a612 --- /dev/null +++ b/src/lib/components/UserDocsLink.tsx @@ -0,0 +1,87 @@ +import { Button, Flex, Text } from "@chakra-ui/react"; +import Link from "next/link"; + +import { trackWebsite } from "lib/amplitude"; +import { DOCS_LINK } from "lib/data"; + +import { CustomIcon } from "./icon"; + +interface UserDocsLinkProps { + href?: string; + title?: string; + cta?: string; + isButton?: boolean; + isSmall?: boolean; + mt?: number; +} + +export const UserDocsLink = ({ + title, + cta, + href, + isButton = false, + isSmall = true, + mt = 8, +}: UserDocsLinkProps) => + isButton ? ( + { + trackWebsite(`${DOCS_LINK}/${href}`); + e.stopPropagation(); + }} + target="_blank" + rel="noopener noreferrer" + > + + + ) : ( + + {title && ( + + {title} + + )} + + *": { + color: "secondary.light", + textDecoration: "underline", + transition: "all", + transitionDuration: "0.25s", + transitionTimingFunction: "ease-in-out", + }, + }, + }} + > + + + {cta} + + + + + ); diff --git a/src/lib/data/constant.ts b/src/lib/data/constant.ts index bffee8350..e9fac0652 100644 --- a/src/lib/data/constant.ts +++ b/src/lib/data/constant.ts @@ -12,6 +12,8 @@ import { MsgType } from "lib/types"; */ import { formatSlugName } from "lib/utils/format"; +export const DOCS_LINK = "https://docs.alleslabs.com/user-guide"; + export const INSTANTIATED_LIST_NAME = "Instantiated by me"; export const SAVED_LIST_NAME = "Saved Contracts"; diff --git a/src/lib/layout/Footer.tsx b/src/lib/layout/Footer.tsx index fe91df7f3..73de3e192 100644 --- a/src/lib/layout/Footer.tsx +++ b/src/lib/layout/Footer.tsx @@ -4,9 +4,12 @@ import Link from "next/link"; import { CURR_THEME } from "env"; import { AmpEvent, track, trackSocial } from "lib/amplitude"; +import { useMobile } from "lib/app-provider"; import { CustomIcon } from "lib/components/icon"; import type { IconKeys } from "lib/components/icon"; +import { InformationFooter } from "./InformationFooter"; + interface SocialMenuType { url: string; icon: IconKeys; @@ -89,30 +92,6 @@ const SocialMenuRender = ({ ); -const AllesFeedback = () => ( - track(AmpEvent.FEEDBACK)} - > - - - - Feedback - - - -); - const IconLink = ({ href, icon, @@ -162,8 +141,8 @@ const IconLink = ({ ); const Footer = () => { - const isThemed = CURR_THEME.footer; - return isThemed ? ( + const isMobile = useMobile(); + return CURR_THEME.footer ? ( { target="_blank" rel="noopener noreferrer" > - + @@ -192,7 +171,7 @@ const Footer = () => { color="gray.400" textAlign={{ base: "center", md: "left" }} > - {isThemed.description} + {CURR_THEME.footer.description} { /> - + {isMobile && } ) : ( { > - { text1="Made by" text2="Alles Labs" /> + {isMobile && } ); }; diff --git a/src/lib/layout/InformationFooter.tsx b/src/lib/layout/InformationFooter.tsx new file mode 100644 index 000000000..feea3e56c --- /dev/null +++ b/src/lib/layout/InformationFooter.tsx @@ -0,0 +1,92 @@ +import { track } from "@amplitude/analytics-browser"; +import { Flex, Skeleton, Text } from "@chakra-ui/react"; +import Link from "next/link"; + +import { AmpEvent, trackWebsite } from "lib/amplitude"; +import type { IconKeys } from "lib/components/icon"; +import { CustomIcon } from "lib/components/icon"; +import { DOCS_LINK } from "lib/data"; +import { useOverviewsStats } from "lib/services/overviewService"; + +const FOOTER_BUTTONS = [ + { + href: `${DOCS_LINK}/introduction/user-introduction`, + icon: "document" as IconKeys, + text: "View Doc", + onClick: () => trackWebsite(`${DOCS_LINK}/introduction/user-introduction`), + }, + { + href: "https://feedback.alleslabs.com", + icon: "feedback" as IconKeys, + text: "Feedback", + onClick: () => track(AmpEvent.FEEDBACK), + }, +]; + +export const InformationFooter = () => { + const { data: overviewsStats, isLoading } = useOverviewsStats(); + + return ( + + {isLoading ? ( + + ) : ( + + + + {overviewsStats?.latestBlock ?? "N/A"} + + {overviewsStats && ( + + )} + + )} + + {FOOTER_BUTTONS.map(({ href, icon, text, onClick }) => ( + + + + + {text} + + + + ))} + + + ); +}; diff --git a/src/lib/layout/navbar/Expand.tsx b/src/lib/layout/navbar/Expand.tsx index 6a628bde7..99a301cea 100644 --- a/src/lib/layout/navbar/Expand.tsx +++ b/src/lib/layout/navbar/Expand.tsx @@ -11,6 +11,7 @@ import { Text, } from "@chakra-ui/react"; +import { InformationFooter } from "../InformationFooter"; import { AmpEvent, track } from "lib/amplitude"; import { useNavContext } from "lib/app-provider"; import { AppLink } from "lib/components/AppLink"; @@ -166,34 +167,42 @@ export const ExpandNavMenu = ({ const restNavMenu = navMenu.slice(1); return ( - - - - {yourAccountMenu.category} - - - - - - - {restNavMenu.map((item) => ( - +
+ + + {yourAccountMenu.category} + + + + - ))} - + {restNavMenu.map((item) => ( + + ))} +
+ +
); }; diff --git a/src/lib/pages/account-details/index.tsx b/src/lib/pages/account-details/index.tsx index 02345878a..4e52921ca 100644 --- a/src/lib/pages/account-details/index.tsx +++ b/src/lib/pages/account-details/index.tsx @@ -26,6 +26,7 @@ import { CustomTab } from "lib/components/CustomTab"; import { CustomIcon } from "lib/components/icon"; import PageContainer from "lib/components/PageContainer"; import { InvalidState } from "lib/components/state"; +import { UserDocsLink } from "lib/components/UserDocsLink"; import { useFormatAddresses } from "lib/hooks/useFormatAddresses"; import { useAccountData } from "lib/services/accountService"; import { useModulesByAddress } from "lib/services/move/moduleService"; @@ -401,12 +402,27 @@ const AccountDetailsBody = ({ )} /> )} + + + @@ -417,6 +433,11 @@ const AccountDetailsBody = ({ scrollComponentId={tableHeaderId} refetchCount={refetchCounts} /> + + + + + diff --git a/src/lib/pages/admin/index.tsx b/src/lib/pages/admin/index.tsx index 038635a5d..3c96a0d2f 100644 --- a/src/lib/pages/admin/index.tsx +++ b/src/lib/pages/admin/index.tsx @@ -20,6 +20,7 @@ import { ErrorMessageRender } from "lib/components/ErrorMessageRender"; import { EstimatedFeeRender } from "lib/components/EstimatedFeeRender"; import type { FormStatus } from "lib/components/forms"; import { TextInput } from "lib/components/forms"; +import { UserDocsLink } from "lib/components/UserDocsLink"; import WasmPageContainer from "lib/components/WasmPageContainer"; import { useTxBroadcast } from "lib/providers/tx-broadcast"; import { useContractDetailByContractAddress } from "lib/services/contractService"; @@ -169,9 +170,16 @@ const UpdateAdmin = () => { return ( - - Update Admin - + + + Update Admin + + + { const { currentChainId } = useCelatoneApp(); return ( - - Block Info - + + + Block Info + + + diff --git a/src/lib/pages/blocks/index.tsx b/src/lib/pages/blocks/index.tsx index 2cbfbeb65..3bdfe9fed 100644 --- a/src/lib/pages/blocks/index.tsx +++ b/src/lib/pages/blocks/index.tsx @@ -1,9 +1,9 @@ -import { Heading, Text } from "@chakra-ui/react"; import { useRouter } from "next/router"; import { useEffect } from "react"; import { AmpEvent, track } from "lib/amplitude"; import PageContainer from "lib/components/PageContainer"; +import { PageHeader } from "lib/components/PageHeader"; import { BlocksTable } from "./components/BlocksTable"; @@ -16,12 +16,11 @@ const BlocksPage = () => { return ( - - Blocks - - - This page displays all blocks on this network sorted by recency - + ); diff --git a/src/lib/pages/code-details/index.tsx b/src/lib/pages/code-details/index.tsx index b9b18b8bf..eb922eff5 100644 --- a/src/lib/pages/code-details/index.tsx +++ b/src/lib/pages/code-details/index.tsx @@ -14,6 +14,7 @@ import { CustomTab } from "lib/components/CustomTab"; import { Loading } from "lib/components/Loading"; import PageContainer from "lib/components/PageContainer"; import { ErrorFetching, InvalidState } from "lib/components/state"; +import { UserDocsLink } from "lib/components/UserDocsLink"; import { useSchemaStore } from "lib/providers/store"; import { useCodeDataByCodeId } from "lib/services/codeService"; @@ -108,6 +109,11 @@ const CodeDetailsBody = observer(({ codeId, tab }: CodeDetailsBodyProps) => { toJsonSchemaTab={handleTabChange(TabIndex.JsonSchema)} /> + { codeHash={code.hash} jsonSchema={jsonSchema} /> + diff --git a/src/lib/pages/codes/index.tsx b/src/lib/pages/codes/index.tsx index a56d133f4..7651f8187 100644 --- a/src/lib/pages/codes/index.tsx +++ b/src/lib/pages/codes/index.tsx @@ -1,4 +1,4 @@ -import { Box, Heading, Text } from "@chakra-ui/react"; +import { Box } from "@chakra-ui/react"; import { observer } from "mobx-react-lite"; import { useRouter } from "next/router"; import { useEffect } from "react"; @@ -8,6 +8,7 @@ import { AmpEvent, track } from "lib/amplitude"; import { useWasmConfig } from "lib/app-provider"; import { FilterByPermission } from "lib/components/forms"; import PageContainer from "lib/components/PageContainer"; +import { PageHeader } from "lib/components/PageHeader"; import type { PermissionFilterValue } from "lib/hooks"; import { RecentCodesTable } from "./components/RecentCodesTable"; @@ -33,23 +34,20 @@ const RecentCodes = observer(() => { return ( - - - Codes - - - This page displays all codes on this network sorted by recency - - - { - if (newVal === permissionValue) return; - setValue("permissionValue", newVal); - }} - /> - + + + { + if (newVal === permissionValue) return; + setValue("permissionValue", newVal); + }} + /> diff --git a/src/lib/pages/contract-details/index.tsx b/src/lib/pages/contract-details/index.tsx index 6aa08da02..2fcc9f268 100644 --- a/src/lib/pages/contract-details/index.tsx +++ b/src/lib/pages/contract-details/index.tsx @@ -27,6 +27,7 @@ import { JsonInfo } from "lib/components/json/JsonInfo"; import { Loading } from "lib/components/Loading"; import PageContainer from "lib/components/PageContainer"; import { ErrorFetching, InvalidState } from "lib/components/state"; +import { UserDocsLink } from "lib/components/UserDocsLink"; import { useBalances } from "lib/services/balanceService"; import type { BechAddr32 } from "lib/types"; import { jsonPrettify } from "lib/utils"; @@ -234,18 +235,43 @@ const ContractDetailsBody = observer( + + + + + diff --git a/src/lib/pages/contract-list/index.tsx b/src/lib/pages/contract-list/index.tsx index e12a66f63..9d0d7cc92 100644 --- a/src/lib/pages/contract-list/index.tsx +++ b/src/lib/pages/contract-list/index.tsx @@ -9,6 +9,7 @@ import { CustomIcon } from "lib/components/icon"; import { CreateNewListModal } from "lib/components/modal"; import PageContainer from "lib/components/PageContainer"; import { AllContractLists } from "lib/components/select-contract"; +import { UserDocsLink } from "lib/components/UserDocsLink"; import { useInstantiatedMockInfoByMe } from "lib/model/contract"; import { useContractStore } from "lib/providers/store"; @@ -50,6 +51,11 @@ const AllContractListsPage = observer(() => { isReadOnly={false} /> + ); }); diff --git a/src/lib/pages/contract-list/slug.tsx b/src/lib/pages/contract-list/slug.tsx index 9acfdf83a..0804aa565 100644 --- a/src/lib/pages/contract-list/slug.tsx +++ b/src/lib/pages/contract-list/slug.tsx @@ -22,6 +22,7 @@ import { } from "lib/components/modal"; import PageContainer from "lib/components/PageContainer"; import { ContractListDetail } from "lib/components/select-contract"; +import { UserDocsLink } from "lib/components/UserDocsLink"; import { INSTANTIATED_LIST_NAME, SAVED_LIST_NAME } from "lib/data"; import { useInstantiatedByMe } from "lib/model/contract"; import { useContractStore } from "lib/providers/store"; @@ -106,7 +107,14 @@ const ContractsByList = observer(() => { {contractListInfo.contracts.length} - + + {isInstantiatedByMe && ( + + )} {isInstantiatedByMe ? ( - ); }; diff --git a/src/lib/pages/execute/index.tsx b/src/lib/pages/execute/index.tsx index 3087df681..d26489e75 100644 --- a/src/lib/pages/execute/index.tsx +++ b/src/lib/pages/execute/index.tsx @@ -1,4 +1,4 @@ -import { Box, Button, Flex, Heading } from "@chakra-ui/react"; +import { Button, Flex, Heading } from "@chakra-ui/react"; import type { Coin } from "@cosmjs/stargate"; import { useRouter } from "next/router"; import { useCallback, useEffect, useState } from "react"; @@ -9,6 +9,7 @@ import { ConnectWalletAlert } from "lib/components/ConnectWalletAlert"; import { ContractSelectSection } from "lib/components/ContractSelectSection"; import { CustomIcon } from "lib/components/icon"; import PageContainer from "lib/components/PageContainer"; +import { UserDocsLink } from "lib/components/UserDocsLink"; import type { ContractDetail } from "lib/services/contractService"; import type { BechAddr32 } from "lib/types"; import { @@ -98,24 +99,22 @@ const Execute = () => { Execute Contract - - - + - { sx={{ "& > div": { zIndex: 1 } }} > - - - {prettyName} - {" "} - Overview - + + + + {prettyName} + {" "} + Overview + + + { DEPLOY NEW CONTRACT - - Instantiate new contract - + + + Instantiate new contract + + + - - Migrate Options - + + + Migrate Options + + + + {address && !isAllowed && ( { return ( - - Past Transactions - + + + Past Transactions + + + { return ( - - Osmosis Pools - + + + + Osmosis Pools + + + This page displays liquidity pools on this network sorted by recency + + + + { + ); }; diff --git a/src/lib/pages/proposal-details/index.tsx b/src/lib/pages/proposal-details/index.tsx index 92fd55a59..e4f14ce88 100644 --- a/src/lib/pages/proposal-details/index.tsx +++ b/src/lib/pages/proposal-details/index.tsx @@ -8,6 +8,7 @@ import { CustomTab } from "lib/components/CustomTab"; import { Loading } from "lib/components/Loading"; import PageContainer from "lib/components/PageContainer"; import { ErrorFetching, InvalidState } from "lib/components/state"; +import { UserDocsLink } from "lib/components/UserDocsLink"; import { useProposalVotesInfo } from "lib/services/proposalService"; import { ProposalOverview, ProposalTop, VoteDetails } from "./components"; @@ -77,6 +78,11 @@ const ProposalDetailsBody = ({ id, tab }: ProposalDetailsQueryParams) => { params={params} isLoading={isVotesInfoLoading || isParamsLoading} /> + { params={params} isLoading={isVotesInfoLoading || isParamsLoading} /> + diff --git a/src/lib/pages/proposals/index.tsx b/src/lib/pages/proposals/index.tsx index 7e3edd249..d38c4c310 100644 --- a/src/lib/pages/proposals/index.tsx +++ b/src/lib/pages/proposals/index.tsx @@ -17,6 +17,7 @@ import { usePaginator } from "lib/components/pagination/usePaginator"; import { EmptyState, ErrorFetching } from "lib/components/state"; import { ProposalsTable } from "lib/components/table"; import { Tooltip } from "lib/components/Tooltip"; +import { UserDocsLink } from "lib/components/UserDocsLink"; import { useDebounce } from "lib/hooks"; import { useProposals } from "lib/services/proposalService"; import type { @@ -100,7 +101,14 @@ const Proposals = () => { Proposals - {!isMobile && } + + + {!isMobile && } + diff --git a/src/lib/pages/query/index.tsx b/src/lib/pages/query/index.tsx index a5434cd23..01ff32a53 100644 --- a/src/lib/pages/query/index.tsx +++ b/src/lib/pages/query/index.tsx @@ -1,4 +1,4 @@ -import { Box, Button, Flex, Heading } from "@chakra-ui/react"; +import { Button, Flex, Heading } from "@chakra-ui/react"; import { observer } from "mobx-react-lite"; import { useRouter } from "next/router"; import { useCallback, useEffect, useState } from "react"; @@ -12,6 +12,7 @@ import { import { ContractSelectSection } from "lib/components/ContractSelectSection"; import { CustomIcon } from "lib/components/icon"; import PageContainer from "lib/components/PageContainer"; +import { UserDocsLink } from "lib/components/UserDocsLink"; import type { ContractDetail } from "lib/services/contractService"; import type { BechAddr32 } from "lib/types"; import { @@ -79,20 +80,20 @@ const Query = observer(() => { Query Contract - {!isMobile && ( - + + + {!isMobile && ( - - )} + )} + { ) : ( } /> )} + ); }); diff --git a/src/lib/pages/saved-codes/index.tsx b/src/lib/pages/saved-codes/index.tsx index 811eb9de1..01bc4d743 100644 --- a/src/lib/pages/saved-codes/index.tsx +++ b/src/lib/pages/saved-codes/index.tsx @@ -11,6 +11,7 @@ import { FilterByPermission } from "lib/components/forms"; import InputWithIcon from "lib/components/InputWithIcon"; import PageContainer from "lib/components/PageContainer"; import { MySavedCodesTable } from "lib/components/table"; +import { UserDocsLink } from "lib/components/UserDocsLink"; import type { PermissionFilterValue } from "lib/hooks"; import { useMyCodesData } from "lib/model/code"; @@ -99,6 +100,11 @@ const SavedCodes = observer(() => { isLoading={isSavedCodesLoading} onRowSelect={onRowSelect} /> + ); }); diff --git a/src/lib/pages/stored-codes/index.tsx b/src/lib/pages/stored-codes/index.tsx index 92b44bd2e..21776b11a 100644 --- a/src/lib/pages/stored-codes/index.tsx +++ b/src/lib/pages/stored-codes/index.tsx @@ -15,6 +15,7 @@ import { FilterByPermission } from "lib/components/forms"; import InputWithIcon from "lib/components/InputWithIcon"; import PageContainer from "lib/components/PageContainer"; import { MyStoredCodesTable } from "lib/components/table"; +import { UserDocsLink } from "lib/components/UserDocsLink"; import type { PermissionFilterValue } from "lib/hooks"; import { useMyCodesData } from "lib/model/code"; import { useUploadAccessParams } from "lib/services/proposalService"; @@ -81,25 +82,32 @@ const StoredCodes = observer(() => { {storedCodesCount} - - {isPermissionedNetwork ? ( - <> - - {govConfig.enabled && - !( - govConfig.disableStoreCodeProposal || - govConfig.hideOpenProposal - ) && } - - ) : ( - - )} - + + + + {isPermissionedNetwork ? ( + <> + + {govConfig.enabled && + !( + govConfig.disableStoreCodeProposal || + govConfig.hideOpenProposal + ) && } + + ) : ( + + )} + + { )} + ); }; diff --git a/src/lib/pages/txs/index.tsx b/src/lib/pages/txs/index.tsx index 4dc77b6ef..ffa1c26a5 100644 --- a/src/lib/pages/txs/index.tsx +++ b/src/lib/pages/txs/index.tsx @@ -1,9 +1,9 @@ -import { Heading, Text } from "@chakra-ui/react"; import { useRouter } from "next/router"; import { useEffect } from "react"; import { AmpEvent, track } from "lib/amplitude"; import PageContainer from "lib/components/PageContainer"; +import { PageHeader } from "lib/components/PageHeader"; import { TxsTable } from "./components/TxsTable"; @@ -16,12 +16,12 @@ const Txs = () => { return ( - - Transactions - - - This page displays all transactions on this network sorted by recency - + ); diff --git a/src/lib/pages/upload/upload.tsx b/src/lib/pages/upload/upload.tsx index 150b9d389..1ee85d6e1 100644 --- a/src/lib/pages/upload/upload.tsx +++ b/src/lib/pages/upload/upload.tsx @@ -1,4 +1,4 @@ -import { Heading, Text } from "@chakra-ui/react"; +import { Flex, Heading, Text } from "@chakra-ui/react"; import { useRouter } from "next/router"; import { useEffect } from "react"; @@ -8,6 +8,7 @@ import { useCurrentChain, useInternalNavigate } from "lib/app-provider"; import { ConnectWalletAlert } from "lib/components/ConnectWalletAlert"; import { Stepper } from "lib/components/stepper"; import { UploadSection } from "lib/components/upload/UploadSection"; +import { UserDocsLink } from "lib/components/UserDocsLink"; import WasmPageContainer from "lib/components/WasmPageContainer"; import { useUploadAccessParams } from "lib/services/proposalService"; import { AccessConfigPermission } from "lib/types"; @@ -42,9 +43,16 @@ export const Upload = ({ DEPLOY NEW CONTRACT - - Upload Wasm file - + + + Upload Wasm file + + + { return ( <> - - - Validators - - - This page displays all validators on this network - - +