Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: invalid code #83

Merged
merged 4 commits into from
Jan 13, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Features

- [#83](https://github.com/alleslabs/celatone-frontend/pull/83) Add invalid code state
- [#77](https://github.com/alleslabs/celatone-frontend/pull/77) Wireup code info section in code details page
- [#80](https://github.com/alleslabs/celatone-frontend/pull/80) Fix the misalignment of state in the PastTx page
- [#70](https://github.com/alleslabs/celatone-frontend/pull/70) Change default token denom on contract detail
Expand Down
27 changes: 27 additions & 0 deletions src/lib/components/state/InvalidState.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Flex, Heading, Icon, Text } from "@chakra-ui/react";
import { MdSearchOff } from "react-icons/md";

interface InvalidStateProps {
title: string;
}

export const InvalidState = ({ title }: InvalidStateProps) => (
<Flex
direction="column"
alignItems="center"
borderY="1px solid"
borderColor="divider.main"
width="full"
my="24px"
py="24px"
>
<Icon as={MdSearchOff} color="gray.600" boxSize="128" />
<Heading as="h5" variant="h5" my="8px">
{title}
</Heading>
<Text variant="body2" fontWeight="500" color="gray.500" textAlign="center">
Please double-check your input and make sure you have selected the correct
network.
</Text>
</Flex>
);
6 changes: 3 additions & 3 deletions src/lib/model/code.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,17 @@ import {
useContractListCountByCodeId,
} from "lib/services/codeService";
import type { ContractInfo } from "lib/stores/contract";
import type { CodeDetails, ContractInstances, Option } from "lib/types";
import type { CodeData, ContractInstances, Option } from "lib/types";

export const useCodeData = (codeId: number): Option<CodeDetails> => {
export const useCodeData = (codeId: number): Option<CodeData> => {
const { currentChainRecord } = useWallet();
const { data: codeInfo } = useCodeInfoByCodeId(codeId);
if (!currentChainRecord || !codeInfo) return undefined;

return {
chainId: currentChainRecord.chain.chain_id,
...codeInfo,
} as CodeDetails;
} as CodeData;
};

export const useCodeContractInstances = (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@ import { ExplorerLink } from "lib/components/ExplorerLink";
import { LabelText } from "lib/components/LabelText";
import { PermissionChip } from "lib/components/PermissionChip";
import { useGetAddressType } from "lib/hooks";
import type { CodeDetails, Option, PermissionAddresses } from "lib/types";
import type { CodeData, Option, PermissionAddresses } from "lib/types";
import { dateFromNow, formatUTC, getAddressTypeText } from "lib/utils";

interface CodeInfoSectionProps {
codeDetails: Option<CodeDetails>;
codeData: Option<CodeData>;
}

const getMethodSpecificRender = (
codeProposalInfo: CodeDetails["proposal"],
codeTxInfo: Pick<CodeDetails, "hash" | "height" | "created">
codeProposalInfo: CodeData["proposal"],
codeTxInfo: Pick<CodeData, "hash" | "height" | "created">
): { methodRender: JSX.Element; storedBlockRender: JSX.Element } => {
if (codeProposalInfo) {
return {
Expand Down Expand Up @@ -120,7 +120,7 @@ const ViewAddresses = ({
);
};

const CodeDetailsRender = ({ codeDetails }: { codeDetails: CodeDetails }) => {
const CodeDetailsRender = ({ codeData }: { codeData: CodeData }) => {
const getAddressType = useGetAddressType();
const {
hash,
Expand All @@ -130,7 +130,7 @@ const CodeDetailsRender = ({ codeDetails }: { codeDetails: CodeDetails }) => {
uploader,
instantiatePermission,
permissionAddresses,
} = codeDetails;
} = codeData;
const { methodRender, storedBlockRender } = getMethodSpecificRender(
proposal,
{
Expand All @@ -142,7 +142,7 @@ const CodeDetailsRender = ({ codeDetails }: { codeDetails: CodeDetails }) => {
const uploaderType = getAddressType(uploader);
return (
<Grid templateColumns="repeat(5, 1fr)" columnGap={12}>
<LabelText label="Network">{codeDetails.chainId ?? "unknown"}</LabelText>
<LabelText label="Network">{codeData.chainId ?? "unknown"}</LabelText>
<LabelText label="Uploaded by">
<Flex direction="column" gap={1}>
<ExplorerLink type={uploaderType} value={uploader} canCopyWithHover />
Expand Down Expand Up @@ -170,14 +170,14 @@ const CodeDetailsRender = ({ codeDetails }: { codeDetails: CodeDetails }) => {
);
};

export const CodeInfoSection = ({ codeDetails }: CodeInfoSectionProps) => {
export const CodeInfoSection = ({ codeData }: CodeInfoSectionProps) => {
return (
<Box mb={12}>
<Heading as="h6" variant="h6" mb={6}>
Code Information
</Heading>
{codeDetails ? (
<CodeDetailsRender codeDetails={codeDetails} />
{codeData ? (
<CodeDetailsRender codeData={codeData} />
) : (
<Text variant="body2" color="text.dark">
Error fetching data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,28 @@ import { useRouter } from "next/router";
import { BackButton } from "lib/components/button/BackButton";
import { ExplorerLink } from "lib/components/ExplorerLink";
import PageContainer from "lib/components/PageContainer";
import { InvalidState } from "lib/components/state/InvalidState";
import { useCodeStore } from "lib/hooks";
import { useCodeData } from "lib/model/code";
import { InstantiatePermission } from "lib/types";
import { getFirstQueryParam } from "lib/utils";
import { getFirstQueryParam, isCodeId } from "lib/utils";

import { CodeInfoSection } from "./component/CodeInfoSection";
import { CTASection } from "./component/CTASection";

const CodeDetails = observer(() => {
const router = useRouter();
/**
* @todos Handle incorrect codeIdParam and render not found or error page.
*/
const codeIdParam = getFirstQueryParam(router.query.codeId);
const codeId = Number(codeIdParam);
interface CodeDetailsBodyProps {
codeId: number;
}

const InvalidCode = () => <InvalidState title="Code does not exist" />;

const CodeDetailsBody = ({ codeId }: CodeDetailsBodyProps) => {
const { getCodeLocalInfo } = useCodeStore();
const localCodeInfo = getCodeLocalInfo(codeId);
const codeDetails = useCodeData(codeId);
/**
* @todos Wireup page with data hook and component functionality/logic
*/
const codeData = useCodeData(codeId);
if (!codeData) return <InvalidCode />;
return (
<PageContainer>
<BackButton />
<>
{/* Code ID and CTAs Section */}
{/* TODO: Wireup CTAs logic and render ExplorerLink for Code ID */}
songwongtp marked this conversation as resolved.
Show resolved Hide resolved
<Flex align="center" justify="space-between" mt={6}>
Expand All @@ -47,16 +44,16 @@ const CodeDetails = observer(() => {
{/* TODO: check default uploader case */}
songwongtp marked this conversation as resolved.
Show resolved Hide resolved
<CTASection
id={codeId}
uploader={codeDetails?.uploader ?? localCodeInfo?.uploader ?? ""}
uploader={codeData?.uploader ?? localCodeInfo?.uploader ?? ""}
songwongtp marked this conversation as resolved.
Show resolved Hide resolved
description={localCodeInfo?.description}
instantiatePermission={
codeDetails?.instantiatePermission ?? InstantiatePermission.UNKNOWN
codeData?.instantiatePermission ?? InstantiatePermission.UNKNOWN
}
permissionAddresses={codeDetails?.permissionAddresses ?? []}
permissionAddresses={codeData?.permissionAddresses ?? []}
/>
</Flex>
<Divider borderColor="divider.main" my={12} />
<CodeInfoSection codeDetails={codeDetails} />
<CodeInfoSection codeData={codeData} />
{/* TODO: Wireup badge count, Create table component and wireup with real data */}
<Flex mb={6} align="center">
<Heading as="h6" variant="h6">
Expand All @@ -69,6 +66,22 @@ const CodeDetails = observer(() => {
<Heading color="error.main" as="h5" variant="h5">
Table Goes Hereeee
</Heading>
</>
);
};

const CodeDetails = observer(() => {
const router = useRouter();
const codeIdParam = getFirstQueryParam(router.query.codeId);

return (
<PageContainer>
<BackButton />
{!isCodeId(codeIdParam) ? (
<InvalidCode />
) : (
<CodeDetailsBody codeId={Number(codeIdParam)} />
)}
</PageContainer>
);
});
Expand Down
25 changes: 2 additions & 23 deletions src/lib/pages/contract-details/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,14 @@ import {
Tabs,
TabPanels,
TabPanel,
Icon,
Text,
} from "@chakra-ui/react";
import { observer } from "mobx-react-lite";
import { useRouter } from "next/router";
import { MdSearchOff } from "react-icons/md";

import { BackButton } from "lib/components/button/BackButton";
import { CustomTab } from "lib/components/CustomTab";
import PageContainer from "lib/components/PageContainer";
import { InvalidState } from "lib/components/state/InvalidState";
import { useValidateAddress } from "lib/hooks";
import {
useContractData,
Expand All @@ -35,26 +33,7 @@ interface ContractDetailsBodyProps {
contractAddress: ContractAddr;
}

const InvalidContract = () => (
<Flex
direction="column"
alignItems="center"
borderY="1px solid"
borderColor="divider.main"
width="full"
my="24px"
py="24px"
>
<Icon as={MdSearchOff} color="gray.600" boxSize="128" />
<Heading as="h5" variant="h5" my="8px">
Contract does not exist
</Heading>
<Text variant="body2" fontWeight="500" color="gray.500" textAlign="center">
Please double-check your spelling and make sure you have selected the
correct network.
</Text>
</Flex>
);
const InvalidContract = () => <InvalidState title="Contract does not exist" />;

const ContractDetailsBody = ({ contractAddress }: ContractDetailsBodyProps) => {
const contractData = useContractData(contractAddress);
Expand Down
4 changes: 2 additions & 2 deletions src/lib/services/codeService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
import type { ContractInfo } from "lib/stores/contract";
import type {
CodeInfo,
CodeDetails,
CodeData,
ContractAddr,
Option,
InstantiatePermission,
Expand Down Expand Up @@ -81,7 +81,7 @@ export const useCodeListByIDsQuery = (ids: Option<number[]>) => {

export const useCodeInfoByCodeId = (
codeId: Option<number>
): UseQueryResult<Option<Omit<CodeDetails, "chainId">>> => {
): UseQueryResult<Option<Omit<CodeData, "chainId">>> => {
const queryFn = useCallback(async () => {
if (!codeId) return undefined;

Expand Down
2 changes: 1 addition & 1 deletion src/lib/types/code.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ interface CodeProposal {
created: Date;
}

export interface CodeDetails {
export interface CodeData {
chainId: Option<string>;
codeId: number;
uploader: ContractAddr | HumanAddr;
Expand Down
2 changes: 1 addition & 1 deletion src/pages/code/[codeId].ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import CodeDetails from "lib/pages/code";
import CodeDetails from "lib/pages/code-details";

export default CodeDetails;