diff --git a/CHANGELOG.md b/CHANGELOG.md index 01ff173cf..c5341069b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,6 +43,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Improvements +- [#251](https://github.com/alleslabs/celatone-frontend/pull/251) Refactor Code and Contract tables into general components - [#252](https://github.com/alleslabs/celatone-frontend/pull/252) Refactor Empty State image source logic - [#249](https://github.com/alleslabs/celatone-frontend/pull/249) Change code table format in select code draw and add CW2 info - [#247](https://github.com/alleslabs/celatone-frontend/pull/247) Refactor hover logic of copier icon diff --git a/src/lib/components/select-code/CodeSelectDrawerButton.tsx b/src/lib/components/select-code/CodeSelectDrawerButton.tsx index 93f722ee2..0a107dd68 100644 --- a/src/lib/components/select-code/CodeSelectDrawerButton.tsx +++ b/src/lib/components/select-code/CodeSelectDrawerButton.tsx @@ -21,13 +21,11 @@ import { CustomTab } from "../CustomTab"; import { FilterByPermission } from "../forms"; import { CustomIcon } from "../icon"; import InputWithIcon from "../InputWithIcon"; +import { MySavedCodesTable, MyStoredCodesTable } from "../table"; import type { PermissionFilterValue } from "lib/hooks"; import { useMyCodesData } from "lib/model/code"; import { AmpEvent, AmpTrack } from "lib/services/amplitude"; -import { MySavedCodeContent } from "./MySavedCodeContent"; -import { MyStoredCodeContent } from "./MyStoredCodeContent"; - interface CodeFilterState { keyword: string; permissionValue: PermissionFilterValue; @@ -66,11 +64,13 @@ export const CodeSelectDrawerButton = ({ isSavedCodesLoading, } = useMyCodesData(keyword, permissionValue); - const handleSelect = (code: string) => { - onCodeSelect(code); + const handleSelect = (codeId: number) => { + onCodeSelect(codeId.toString()); onClose(); }; + const isSearching = !!keyword || permissionValue !== "all"; + return ( <> - - - - - - - - - - - - - } - > - Edit details - - } - /> - } - > - Add or remove from other lists - - } - /> - } - onClick={() => { - navigate({ - pathname: "/admin", - query: { contract: item.contractAddress }, - }); - }} - isDisabled={!isAdmin} - > - Update Admin - - - } - isDisabled={!isAdmin} - > - Clear Admin - - } - /> - {!!contractRemovalInfo && ( - <> - - - ), - children: "Remove from this list", - }} - /> - - )} - - - - - - - ); - })} - - ); -}; diff --git a/src/lib/components/select-contract/SelectContractAdmin.tsx b/src/lib/components/select-contract/SelectContractAdmin.tsx index 26715a902..d4bbc9136 100644 --- a/src/lib/components/select-contract/SelectContractAdmin.tsx +++ b/src/lib/components/select-contract/SelectContractAdmin.tsx @@ -35,7 +35,9 @@ export const SelectContractAdmin = ({ const { address } = useWallet(); const { getContractLocalInfo } = useContractStore(); - const { data: contracts = [] } = useContractListByAdmin(address as HumanAddr); + const { data: contracts = [], isLoading } = useContractListByAdmin( + address as HumanAddr + ); const contractList: ContractListInfo = { name: ADMIN_SPECIAL_SLUG, slug: ADMIN_SPECIAL_SLUG, @@ -87,6 +89,7 @@ export const SelectContractAdmin = ({ diff --git a/src/lib/components/select-contract/SelectContractInstantiator.tsx b/src/lib/components/select-contract/SelectContractInstantiator.tsx index 33361227a..0186ff05b 100644 --- a/src/lib/components/select-contract/SelectContractInstantiator.tsx +++ b/src/lib/components/select-contract/SelectContractInstantiator.tsx @@ -57,10 +57,8 @@ export const SelectContractInstantiator = ({ const { getContractLists } = useContractStore(); // TODO - Revisit false case - const contractLists = [ - useInstantiatedByMe(true).instantiatedListInfo, - ...getContractLists(), - ]; + const { instantiatedListInfo, isLoading } = useInstantiatedByMe(true); + const contractLists = [instantiatedListInfo, ...getContractLists()]; const contractList = contractLists.find((item) => item.slug === listSlug); const endpoint = useLCDEndpoint(); @@ -201,6 +199,7 @@ export const SelectContractInstantiator = ({ diff --git a/src/lib/components/select-contract/index.ts b/src/lib/components/select-contract/index.ts index a8df86c5c..896d9c9ad 100644 --- a/src/lib/components/select-contract/index.ts +++ b/src/lib/components/select-contract/index.ts @@ -1,7 +1,5 @@ export * from "./AllContractLists"; export * from "./ContractListCard"; export * from "./ContractListDetail"; -export * from "./ContractListReadOnlyTable"; -export * from "./ContractListTable"; export * from "./SelectContractAdmin"; export * from "./SelectContractInstantiator"; diff --git a/src/lib/components/state/DisconnectedState.tsx b/src/lib/components/state/DisconnectedState.tsx index 157405abd..3f9430fe0 100644 --- a/src/lib/components/state/DisconnectedState.tsx +++ b/src/lib/components/state/DisconnectedState.tsx @@ -2,6 +2,8 @@ import { Flex, Text } from "@chakra-ui/react"; import { ConnectWalletBtn } from "../button/ConnectWallet"; +import { StateImage } from "./StateImage"; + interface DisconnectedStateProps { text: string; helperText?: string; @@ -11,7 +13,8 @@ export const DisconnectedState = ({ text, helperText, }: DisconnectedStateProps) => ( - <> + + @@ -30,5 +33,5 @@ export const DisconnectedState = ({ {helperText} )} - + ); diff --git a/src/lib/components/state/EmptyState.tsx b/src/lib/components/state/EmptyState.tsx index 46ef82042..ef4e1c695 100644 --- a/src/lib/components/state/EmptyState.tsx +++ b/src/lib/components/state/EmptyState.tsx @@ -1,6 +1,7 @@ -import { Flex, Text, Image, Heading } from "@chakra-ui/react"; +import { Flex, Text, Heading } from "@chakra-ui/react"; -type ImageVariant = "empty" | "not-found"; +import type { ImageVariant } from "./StateImage"; +import { StateImage } from "./StateImage"; interface EmptyStateProps { imageVariant?: ImageVariant; @@ -9,11 +10,6 @@ interface EmptyStateProps { withBorder?: boolean; } -const imageSourceMap: Record = { - empty: "https://assets.alleslabs.dev/illustration/search-empty.svg", - "not-found": "https://assets.alleslabs.dev/illustration/search-not-found.svg", -}; - export const EmptyState = ({ message, imageVariant, @@ -27,13 +23,7 @@ export const EmptyState = ({ borderColor="pebble.700" > - {imageVariant && ( - result not found - )} + {imageVariant && } {heading && ( {heading} diff --git a/src/lib/components/state/InvalidState.tsx b/src/lib/components/state/InvalidState.tsx index 946ecd3b0..96316729e 100644 --- a/src/lib/components/state/InvalidState.tsx +++ b/src/lib/components/state/InvalidState.tsx @@ -1,9 +1,11 @@ -import { Flex, Heading, Image, Text } from "@chakra-ui/react"; +import { Flex, Heading, Text } from "@chakra-ui/react"; import { useRouter } from "next/router"; import { useEffect } from "react"; import { AmpTrackInvalidState } from "lib/services/amplitude"; +import { StateImage } from "./StateImage"; + interface InvalidStateProps { title: string; } @@ -24,11 +26,7 @@ export const InvalidState = ({ title }: InvalidStateProps) => { my="24px" py="24px" > - result not found + {title} diff --git a/src/lib/components/state/StateImage.tsx b/src/lib/components/state/StateImage.tsx new file mode 100644 index 000000000..62702317f --- /dev/null +++ b/src/lib/components/state/StateImage.tsx @@ -0,0 +1,21 @@ +import { Image } from "@chakra-ui/react"; + +export type ImageVariant = "empty" | "not-found" | "disconnected"; + +const imageSourceMap: Record = { + empty: "https://assets.alleslabs.dev/illustration/search-empty.svg", + "not-found": "https://assets.alleslabs.dev/illustration/search-not-found.svg", + disconnected: "https://assets.alleslabs.dev/illustration/disconnected.svg", +}; + +interface StateImageProps { + imageVariant: ImageVariant; +} + +export const StateImage = ({ imageVariant }: StateImageProps) => ( + result not found +); diff --git a/src/lib/components/state/ZeroState.tsx b/src/lib/components/state/ZeroState.tsx index 5e9f50a8c..903328963 100644 --- a/src/lib/components/state/ZeroState.tsx +++ b/src/lib/components/state/ZeroState.tsx @@ -1,4 +1,4 @@ -import { Flex, Button, Image, Text } from "@chakra-ui/react"; +import { Flex, Button, Text } from "@chakra-ui/react"; import { CustomIcon } from "../icon"; import { useInternalNavigate } from "lib/app-provider"; @@ -7,6 +7,8 @@ import { ADMIN_SPECIAL_SLUG, INSTANTIATED_LIST_NAME } from "lib/data"; import type { LVPair } from "lib/types"; import { formatSlugName } from "lib/utils"; +import { StateImage } from "./StateImage"; + interface ZeroStateProps { list: LVPair; isReadOnly?: boolean; @@ -72,11 +74,7 @@ export const ZeroState = ({ list, isReadOnly }: ZeroStateProps) => { alignContent="center" > - result not found + {renderText(list.value)} {!isReadOnly && ( )} - {!!onSave && ( + {!!onSave && !isReadOnly && ( { +export const CodeNameCell = ({ + code, + isReadOnly = false, +}: CodeNameCellProps) => { const toast = useToast(); const { updateCodeInfo } = useCodeStore(); @@ -33,6 +37,7 @@ export const CodeNameCell = ({ code }: CodeNameCellProps) => { defaultValue="Untitled Name" maxLength={MAX_CODE_NAME_LENGTH} onSave={onSave} + isReadOnly={isReadOnly} /> ); }; diff --git a/src/lib/components/table/codes/CodesTable.tsx b/src/lib/components/table/codes/CodesTable.tsx index 34ee6944e..fe8b0f622 100644 --- a/src/lib/components/table/codes/CodesTable.tsx +++ b/src/lib/components/table/codes/CodesTable.tsx @@ -9,27 +9,37 @@ interface CodesTableProps { codes: Option; isLoading: boolean; emptyState: JSX.Element; + onRowSelect: (codeId: number) => void; + isReadOnly?: boolean; } export const CodesTable = ({ codes, isLoading, emptyState, + onRowSelect, + isReadOnly = false, }: CodesTableProps) => { if (isLoading) return ; if (!codes?.length) return emptyState; - const templateColumns = - "max(80px) minmax(320px, 1fr) max(120px) max(160px) minmax(320px, 0.75fr)"; + const templateColumns = isReadOnly + ? "max(100px) minmax(250px, 1fr) minmax(200px, 1fr) max(100px) max(160px) 150px" + : "max(100px) minmax(250px, 1fr) minmax(200px, 1fr) max(100px) max(160px) 150px 180px"; return ( - + {codes.map((code) => ( ))} diff --git a/src/lib/components/table/codes/CodesTableHeader.tsx b/src/lib/components/table/codes/CodesTableHeader.tsx index b3f46f2c2..6268171bb 100644 --- a/src/lib/components/table/codes/CodesTableHeader.tsx +++ b/src/lib/components/table/codes/CodesTableHeader.tsx @@ -5,14 +5,18 @@ import { TableHeader } from "../tableComponents"; export const CodesTableHeader = ({ templateColumns, + isReadOnly, }: { templateColumns: GridProps["templateColumns"]; + isReadOnly: boolean; }) => ( - Code ID + Code ID Code Name - Contracts + CW2 Info + Contracts Uploader Permission + {!isReadOnly && } ); diff --git a/src/lib/components/table/codes/CodesTableRow.tsx b/src/lib/components/table/codes/CodesTableRow.tsx index fd879a0ec..8c008696a 100644 --- a/src/lib/components/table/codes/CodesTableRow.tsx +++ b/src/lib/components/table/codes/CodesTableRow.tsx @@ -1,35 +1,33 @@ -import { Flex, Text, Grid, HStack } from "@chakra-ui/react"; +import { Text, Grid, HStack } from "@chakra-ui/react"; import { TableRow } from "../tableComponents"; -import { useInternalNavigate } from "lib/app-provider"; import { InstantiateButton } from "lib/components/button"; import { ExplorerLink } from "lib/components/ExplorerLink"; import { SaveOrRemoveCodeModal } from "lib/components/modal"; import { PermissionChip } from "lib/components/PermissionChip"; import type { CodeInfo } from "lib/types"; +import { getCw2Info } from "lib/utils"; import { CodeNameCell } from "./CodeNameCell"; interface CodesTableRowProps { codeInfo: CodeInfo; templateColumns: string; + onRowSelect: (codeId: number) => void; + isReadOnly: boolean; } export const CodesTableRow = ({ codeInfo, templateColumns, + onRowSelect, + isReadOnly, }: CodesTableRowProps) => { - const navigate = useInternalNavigate(); - + const cw2Info = getCw2Info(codeInfo.cw2Contract, codeInfo.cw2Version); return ( - navigate({ - pathname: "/code/[codeId]", - query: { codeId: codeInfo.id }, - }) - } + onClick={() => onRowSelect(codeInfo.id)} _hover={{ bg: "pebble.900" }} transition="all .25s ease-in-out" cursor="pointer" @@ -43,16 +41,22 @@ export const CodesTableRow = ({ /> - + + + {cw2Info ?? "N/A"} + + + e.stopPropagation()} cursor="text" - w="fit-content" - m="auto" - px={2} + color={codeInfo.contractCount ? "text.main" : "text.disabled"} > {codeInfo.contractCount ?? "N/A"} @@ -62,14 +66,17 @@ export const CodesTableRow = ({ value={codeInfo.uploader} type="user_address" showCopyOnHover + isReadOnly={isReadOnly} /> - - + + + {!isReadOnly && ( + e.stopPropagation()}> - - + + )} ); }; diff --git a/src/lib/components/table/codes/CodesTableWithWallet.tsx b/src/lib/components/table/codes/CodesTableWithWallet.tsx new file mode 100644 index 000000000..75d394e14 --- /dev/null +++ b/src/lib/components/table/codes/CodesTableWithWallet.tsx @@ -0,0 +1,45 @@ +import { Flex } from "@chakra-ui/react"; +import { useWallet } from "@cosmos-kit/react"; + +import { DisconnectedState } from "lib/components/state"; +import type { CodeInfo } from "lib/types"; + +import { CodesTable } from "./CodesTable"; + +interface CodesTableWithWalletProps { + codes: CodeInfo[]; + isLoading: boolean; + emptyState: JSX.Element; + onRowSelect: (codeId: number) => void; + disconnectedMessage: string; + isReadOnly?: boolean; +} + +export const CodesTableWithWallet = ({ + codes, + isLoading, + emptyState, + onRowSelect, + disconnectedMessage, + isReadOnly = false, +}: CodesTableWithWalletProps) => { + const { address } = useWallet(); + return !address ? ( + + + + ) : ( + + ); +}; diff --git a/src/lib/components/table/codes/MySavedCodesTable.tsx b/src/lib/components/table/codes/MySavedCodesTable.tsx new file mode 100644 index 000000000..3987a66e6 --- /dev/null +++ b/src/lib/components/table/codes/MySavedCodesTable.tsx @@ -0,0 +1,36 @@ +import { EmptyState } from "lib/components/state"; +import type { CodeInfo } from "lib/types"; + +import { CodesTable } from "./CodesTable"; + +interface MySavedCodesTableProps { + codes: CodeInfo[]; + isLoading: boolean; + onRowSelect: (codeId: number) => void; + emptyMessage: string; + isSearching: boolean; + isReadOnly?: boolean; +} + +export const MySavedCodesTable = ({ + codes, + isLoading, + onRowSelect, + emptyMessage, + isSearching, + isReadOnly = false, +}: MySavedCodesTableProps) => ( + + } + onRowSelect={onRowSelect} + isReadOnly={isReadOnly} + /> +); diff --git a/src/lib/components/table/codes/MyStoredCodesTable.tsx b/src/lib/components/table/codes/MyStoredCodesTable.tsx new file mode 100644 index 000000000..9af08c23c --- /dev/null +++ b/src/lib/components/table/codes/MyStoredCodesTable.tsx @@ -0,0 +1,39 @@ +import { EmptyState } from "lib/components/state"; +import type { CodeInfo } from "lib/types"; + +import { CodesTableWithWallet } from "./CodesTableWithWallet"; + +interface MyStoredCodesTableProps { + codes: CodeInfo[]; + isLoading: boolean; + onRowSelect: (codeId: number) => void; + emptyMessage: string; + disconnectedMessage: string; + isSearching: boolean; + isReadOnly?: boolean; +} + +export const MyStoredCodesTable = ({ + codes, + isLoading, + onRowSelect, + emptyMessage, + disconnectedMessage, + isSearching, + isReadOnly = false, +}: MyStoredCodesTableProps) => ( + + } + onRowSelect={onRowSelect} + disconnectedMessage={disconnectedMessage} + isReadOnly={isReadOnly} + /> +); diff --git a/src/lib/components/table/codes/index.ts b/src/lib/components/table/codes/index.ts index ef207ab4d..36ad425ae 100644 --- a/src/lib/components/table/codes/index.ts +++ b/src/lib/components/table/codes/index.ts @@ -1,2 +1,5 @@ -export * from "./CodesTable"; export * from "./CodeNameCell"; +export * from "./CodesTable"; +export * from "./CodesTableWithWallet"; +export * from "./MySavedCodesTable"; +export * from "./MyStoredCodesTable"; diff --git a/src/lib/components/table/contracts/ContractsTable.tsx b/src/lib/components/table/contracts/ContractsTable.tsx index 56476bdba..30433eb18 100644 --- a/src/lib/components/table/contracts/ContractsTable.tsx +++ b/src/lib/components/table/contracts/ContractsTable.tsx @@ -1,30 +1,42 @@ import { TableContainer } from "../tableComponents"; import { Loading } from "lib/components/Loading"; -import type { ContractInfo, Option } from "lib/types"; +import type { ContractAddr, ContractInfo, Option } from "lib/types"; import { ContractsTableHeader } from "./ContractsTableHeader"; import { ContractsTableRow } from "./ContractsTableRow"; +import type { CTAInfo } from "./ContractsTableRowCTA"; interface ContractsTableProps { contracts: Option; isLoading: boolean; emptyState: JSX.Element; + onRowSelect: (contract: ContractAddr) => void; + isReadOnly?: boolean; + withCTA?: CTAInfo; } export const ContractsTable = ({ contracts, isLoading, emptyState, + onRowSelect, + isReadOnly = false, + withCTA, }: ContractsTableProps) => { if (isLoading) return ; if (!contracts?.length) return emptyState; - const templateColumns = - "150px minmax(250px, 1fr) 200px 150px minmax(250px, 300px) 70px"; + const templateColumns = isReadOnly + ? "minmax(160px, 300px) minmax(300px, 3fr) minmax(200px, 2fr) 1fr" + : "160px minmax(300px, 3fr) minmax(200px, 2fr) 150px 250px 80px"; return ( - + {contracts.map((contractInfo) => ( ))} diff --git a/src/lib/components/table/contracts/ContractsTableHeader.tsx b/src/lib/components/table/contracts/ContractsTableHeader.tsx index 145d0b828..1e35fd5f4 100644 --- a/src/lib/components/table/contracts/ContractsTableHeader.tsx +++ b/src/lib/components/table/contracts/ContractsTableHeader.tsx @@ -3,17 +3,27 @@ import { Grid } from "@chakra-ui/react"; import { TableHeader } from "../tableComponents"; +import type { CTAInfo } from "./ContractsTableRowCTA"; + export const ContractsTableHeader = ({ templateColumns, + isReadOnly, + withCTA, }: { templateColumns: GridProps["templateColumns"]; + isReadOnly: boolean; + withCTA?: CTAInfo; }) => ( - Contract Address + Contract Address Contract Name Tags Instantiator - Timestamp - + {!isReadOnly && ( + <> + {withCTA ? : Timestamp} + + + )} ); diff --git a/src/lib/components/table/contracts/ContractsTableRow.tsx b/src/lib/components/table/contracts/ContractsTableRow.tsx index eb1e4b04b..3a0c913ed 100644 --- a/src/lib/components/table/contracts/ContractsTableRow.tsx +++ b/src/lib/components/table/contracts/ContractsTableRow.tsx @@ -1,44 +1,45 @@ -import { Flex, Text, Grid, IconButton, Box, chakra } from "@chakra-ui/react"; +import { Flex, Text, Grid } from "@chakra-ui/react"; import { TableRow } from "../tableComponents"; -import { useInternalNavigate, useGetAddressType } from "lib/app-provider"; +import { useGetAddressType } from "lib/app-provider"; import { ExplorerLink } from "lib/components/ExplorerLink"; -import { CustomIcon } from "lib/components/icon"; -import { - AddToOtherListModal, - SaveContractDetailsModal, -} from "lib/components/modal"; -import type { ContractInfo } from "lib/types"; +import type { ContractAddr, ContractInfo } from "lib/types"; import { RemarkOperation } from "lib/types"; -import { dateFromNow, formatUTC } from "lib/utils"; import { ContractNameCell } from "./ContractNameCell"; +import type { CTAInfo } from "./ContractsTableRowCTA"; +import { ContractsTableRowCTA } from "./ContractsTableRowCTA"; import { TagsCell } from "./TagsCell"; -const StyledIconButton = chakra(IconButton, { - baseStyle: { - display: "flex", - alignItems: "center", - fontSize: "22px", - borderRadius: "36px", - }, -}); - interface ContractsTableRowProps { contractInfo: ContractInfo; templateColumns: string; + onRowSelect: (contract: ContractAddr) => void; + isReadOnly: boolean; + withCTA?: CTAInfo; } const InstantiatorRender = ({ - contractInfo: { remark, latestUpdater }, -}: Pick) => { + contractInfo: { instantiator, remark, latestUpdater }, + isReadOnly, +}: { + contractInfo: ContractInfo; + isReadOnly: boolean; +}) => { const getAddressType = useGetAddressType(); /** * @remarks handle the case where the data is too old and cannot be found */ if (!latestUpdater) - return ( + return instantiator ? ( + + ) : ( N/A @@ -63,6 +64,7 @@ const InstantiatorRender = ({ value={latestUpdater} type={updaterType} showCopyOnHover + isReadOnly={isReadOnly} /> ); @@ -72,6 +74,7 @@ const InstantiatorRender = ({ value={latestUpdater} type={updaterType} showCopyOnHover + isReadOnly={isReadOnly} /> ); default: @@ -86,93 +89,44 @@ const InstantiatorRender = ({ export const ContractsTableRow = ({ contractInfo, templateColumns, -}: ContractsTableRowProps) => { - const navigate = useInternalNavigate(); + onRowSelect, + isReadOnly, + withCTA, +}: ContractsTableRowProps) => ( + onRowSelect(contractInfo.contractAddress)} + _hover={{ bg: "pebble.900" }} + transition="all .25s ease-in-out" + cursor="pointer" + minW="min-content" + > + + + - return ( - - navigate({ - pathname: `/contract/${contractInfo.contractAddress}`, - }) - } - _hover={{ bg: "pebble.900" }} - transition="all .25s ease-in-out" - cursor="pointer" - minW="min-content" - > - - - + + + - - - + + + - - - + + + - - - - - - e.stopPropagation()} - cursor="text" - > - {contractInfo.latestUpdated ? ( - <> - - {formatUTC(contractInfo.latestUpdated)} - - - {`(${dateFromNow(contractInfo.latestUpdated)})`} - - - ) : ( - - N/A - - )} - - - - - e.stopPropagation()}> - {contractInfo.lists ? ( - - } - variant="ghost-gray" - /> - } - /> - ) : ( - } - variant="ghost-gray" - /> - } - /> - )} - - - - ); -}; + {!isReadOnly && ( + + )} + +); diff --git a/src/lib/components/table/contracts/ContractsTableRowCTA.tsx b/src/lib/components/table/contracts/ContractsTableRowCTA.tsx new file mode 100644 index 000000000..aef7eb2a9 --- /dev/null +++ b/src/lib/components/table/contracts/ContractsTableRowCTA.tsx @@ -0,0 +1,209 @@ +import { + Box, + Button, + chakra, + Flex, + IconButton, + Menu, + MenuButton, + MenuDivider, + MenuItem, + MenuList, + Text, +} from "@chakra-ui/react"; +import { useWallet } from "@cosmos-kit/react"; + +import { TableRow } from "../tableComponents"; +import { useInternalNavigate } from "lib/app-provider"; +import { AppLink } from "lib/components/AppLink"; +import { CustomIcon } from "lib/components/icon"; +import { + AddToOtherListModal, + ClearAdminModal, + EditContractDetailsModal, + RemoveContractModal, + SaveContractDetailsModal, +} from "lib/components/modal"; +import type { ContractInfo, LVPair, Option } from "lib/types"; +import { dateFromNow, formatUTC } from "lib/utils"; + +const StyledMenuItem = chakra(MenuItem, { + baseStyle: { + fontSize: "14px", + }, +}); + +const StyledIconButton = chakra(IconButton, { + baseStyle: { + display: "flex", + alignItems: "center", + fontSize: "22px", + borderRadius: "36px", + }, +}); + +export interface CTAInfo { + removingContractList: Option; +} + +interface ContractsTableRowCTAProps { + contractInfo: ContractInfo; + withCTA?: CTAInfo; +} + +export const ContractsTableRowCTA = ({ + contractInfo, + withCTA, +}: ContractsTableRowCTAProps) => { + const { address } = useWallet(); + const navigate = useInternalNavigate(); + + const isAdmin = !!address && address === contractInfo.admin; + return withCTA ? ( + <> + + e.stopPropagation()} + > + + + + + + + + + + + + + + + + + + + } + > + Edit details + + } + /> + } + > + Add or remove from other lists + + } + /> + } + onClick={() => { + navigate({ + pathname: "/admin", + query: { contract: contractInfo.contractAddress }, + }); + }} + isDisabled={!isAdmin} + > + Update Admin + + } + isDisabled={!isAdmin} + > + Clear Admin + + } + /> + {!!withCTA.removingContractList && ( + <> + + , + children: "Remove from this list", + }} + /> + + )} + + + + + ) : ( + <> + + e.stopPropagation()} + cursor="text" + > + {contractInfo.latestUpdated ? ( + <> + + {formatUTC(contractInfo.latestUpdated)} + + + {`(${dateFromNow(contractInfo.latestUpdated)})`} + + + ) : ( + + N/A + + )} + + + + + e.stopPropagation()}> + {contractInfo.lists ? ( + + } + variant="ghost-gray" + /> + } + /> + ) : ( + } + variant="ghost-gray" + /> + } + /> + )} + + + + ); +}; diff --git a/src/lib/components/table/tableComponents.ts b/src/lib/components/table/tableComponents.ts index 1045b7ffc..04d2fcbb9 100644 --- a/src/lib/components/table/tableComponents.ts +++ b/src/lib/components/table/tableComponents.ts @@ -22,36 +22,16 @@ export const TableHeader = chakra(GridItem, { }, }); -export const TableHeaderNoBorder = chakra(GridItem, { - baseStyle: { - color: "text.main", - fontSize: "12px", - fontWeight: 700, - py: 6, - px: 4, - }, -}); - export const TableRow = chakra(GridItem, { baseStyle: { color: "text.main", fontSize: "14px", fontWeight: 400, p: 4, + minH: "75px", display: "flex", alignItems: "center", borderBottom: "1px solid", borderColor: "pebble.700", }, }); - -export const TableRowNoBorder = chakra(GridItem, { - baseStyle: { - color: "text.main", - fontSize: "14px", - fontWeight: 400, - p: 4, - display: "flex", - alignItems: "center", - }, -}); diff --git a/src/lib/pages/account-details/components/tables/AdminContractsTable.tsx b/src/lib/pages/account-details/components/tables/AdminContractsTable.tsx index 6a73793b8..febc7a8d7 100644 --- a/src/lib/pages/account-details/components/tables/AdminContractsTable.tsx +++ b/src/lib/pages/account-details/components/tables/AdminContractsTable.tsx @@ -1,12 +1,13 @@ import { Box } from "@chakra-ui/react"; import type { ChangeEvent } from "react"; +import { useInternalNavigate } from "lib/app-provider"; import { Pagination } from "lib/components/pagination"; import { usePaginator } from "lib/components/pagination/usePaginator"; import { EmptyState } from "lib/components/state"; import { ContractsTable, TableTitle, ViewMore } from "lib/components/table"; import { useAccountAdminContracts } from "lib/pages/account-details/data"; -import type { HumanAddr, Option } from "lib/types"; +import type { ContractAddr, HumanAddr, Option } from "lib/types"; interface AdminContractsTableProps { walletAddress: HumanAddr; @@ -23,6 +24,13 @@ export const AdminContractsTable = ({ refetchCount, onViewMore, }: AdminContractsTableProps) => { + const navigate = useInternalNavigate(); + const onRowSelect = (contract: ContractAddr) => + navigate({ + pathname: "/contract/[contract]", + query: { contract }, + }); + const { pagesQuantity, currentPage, @@ -68,10 +76,12 @@ export const AdminContractsTable = ({ isLoading={isLoading} emptyState={ } + onRowSelect={onRowSelect} /> {!!totalData && (onViewMore diff --git a/src/lib/pages/account-details/components/tables/InstantiatedContractsTable.tsx b/src/lib/pages/account-details/components/tables/InstantiatedContractsTable.tsx index b772ce915..ac328f9fd 100644 --- a/src/lib/pages/account-details/components/tables/InstantiatedContractsTable.tsx +++ b/src/lib/pages/account-details/components/tables/InstantiatedContractsTable.tsx @@ -1,12 +1,13 @@ import { Box } from "@chakra-ui/react"; import type { ChangeEvent } from "react"; +import { useInternalNavigate } from "lib/app-provider"; import { Pagination } from "lib/components/pagination"; import { usePaginator } from "lib/components/pagination/usePaginator"; import { EmptyState } from "lib/components/state"; import { ContractsTable, TableTitle, ViewMore } from "lib/components/table"; import { useAccountContracts } from "lib/pages/account-details/data"; -import type { HumanAddr, Option } from "lib/types"; +import type { ContractAddr, HumanAddr, Option } from "lib/types"; interface InstantiatedContractsTableProps { walletAddress: HumanAddr; @@ -23,6 +24,13 @@ export const InstantiatedContractsTable = ({ refetchCount, onViewMore, }: InstantiatedContractsTableProps) => { + const navigate = useInternalNavigate(); + const onRowSelect = (contract: ContractAddr) => + navigate({ + pathname: "/contract/[contract]", + query: { contract }, + }); + const { pagesQuantity, currentPage, @@ -68,10 +76,12 @@ export const InstantiatedContractsTable = ({ isLoading={isLoading} emptyState={ } + onRowSelect={onRowSelect} /> {!!totalData && (onViewMore diff --git a/src/lib/pages/account-details/components/tables/OpenedProposalsTable.tsx b/src/lib/pages/account-details/components/tables/OpenedProposalsTable.tsx index 21a33eee2..b6788b538 100644 --- a/src/lib/pages/account-details/components/tables/OpenedProposalsTable.tsx +++ b/src/lib/pages/account-details/components/tables/OpenedProposalsTable.tsx @@ -63,6 +63,7 @@ export const OpenedProposalsTable = ({ isLoading={isLoading} emptyState={ diff --git a/src/lib/pages/account-details/components/tables/StoredCodesTable.tsx b/src/lib/pages/account-details/components/tables/StoredCodesTable.tsx index a0b32bf7c..494ceda8a 100644 --- a/src/lib/pages/account-details/components/tables/StoredCodesTable.tsx +++ b/src/lib/pages/account-details/components/tables/StoredCodesTable.tsx @@ -1,6 +1,7 @@ import { Box } from "@chakra-ui/react"; import type { ChangeEvent } from "react"; +import { useInternalNavigate } from "lib/app-provider"; import { Pagination } from "lib/components/pagination"; import { usePaginator } from "lib/components/pagination/usePaginator"; import { EmptyState } from "lib/components/state"; @@ -23,6 +24,13 @@ export const StoredCodesTable = ({ refetchCount, onViewMore, }: StoredCodesTableProps) => { + const navigate = useInternalNavigate(); + const onRowSelect = (codeId: number) => + navigate({ + pathname: "/code/[codeId]", + query: { codeId }, + }); + const { pagesQuantity, currentPage, @@ -68,10 +76,12 @@ export const StoredCodesTable = ({ isLoading={isLoading} emptyState={ } + onRowSelect={onRowSelect} /> {!!totalData && (onViewMore diff --git a/src/lib/pages/account-details/components/tables/TxsTable.tsx b/src/lib/pages/account-details/components/tables/TxsTable.tsx index 41e418926..c6136aab9 100644 --- a/src/lib/pages/account-details/components/tables/TxsTable.tsx +++ b/src/lib/pages/account-details/components/tables/TxsTable.tsx @@ -82,12 +82,13 @@ const TxsTableBody = ({ emptyState={ !filterSelected.length ? ( ) : ( diff --git a/src/lib/pages/code-details/components/table/CodeContractsTable.tsx b/src/lib/pages/code-details/components/table/CodeContractsTable.tsx index ce0e15b9b..bc015fde5 100644 --- a/src/lib/pages/code-details/components/table/CodeContractsTable.tsx +++ b/src/lib/pages/code-details/components/table/CodeContractsTable.tsx @@ -2,11 +2,13 @@ import { observer } from "mobx-react-lite"; import type { ChangeEvent } from "react"; import { useEffect } from "react"; +import { useInternalNavigate } from "lib/app-provider"; import { Pagination } from "lib/components/pagination"; import { usePaginator } from "lib/components/pagination/usePaginator"; import { ContractsTable, TableTitle } from "lib/components/table"; import { useContractsByCodeId } from "lib/model/contract"; import { useContractListCountByCodeId } from "lib/services/contractService"; +import type { ContractAddr } from "lib/types"; import { NoContracts } from "./NoContracts"; @@ -16,6 +18,13 @@ interface CodeContractsTableProps { export const CodeContractsTable = observer( ({ codeId }: CodeContractsTableProps) => { + const navigate = useInternalNavigate(); + const onRowSelect = (contract: ContractAddr) => + navigate({ + pathname: "/contract/[contract]", + query: { contract }, + }); + const { data: totalData, refetch } = useContractListCountByCodeId(codeId); const { pagesQuantity, @@ -67,6 +76,7 @@ export const CodeContractsTable = observer( contracts={contracts} isLoading={isLoading} emptyState={} + onRowSelect={onRowSelect} /> {!!totalData && totalData > 10 && ( ( - + + No contract instances from this code. @@ -17,17 +26,15 @@ const DisconnectedState = () => ( ); -const EmptyState = () => ( - - No contract instances from this code. - -); - export const NoContracts = () => { const { isWalletConnected } = useWallet(); - return ( - - {!isWalletConnected ? : } - + return !isWalletConnected ? ( + + ) : ( + ); }; diff --git a/src/lib/pages/codes/components/CodesTable.tsx b/src/lib/pages/codes/components/CodesTable.tsx deleted file mode 100644 index 46f93f3ff..000000000 --- a/src/lib/pages/codes/components/CodesTable.tsx +++ /dev/null @@ -1,250 +0,0 @@ -import { - Image, - Heading, - HStack, - VStack, - Text, - Box, - Flex, - Grid, -} from "@chakra-ui/react"; -import { useWallet } from "@cosmos-kit/react"; -import type { ReactNode } from "react"; - -import { useInternalNavigate } from "lib/app-provider"; -import { InstantiateButton } from "lib/components/button"; -import { ExplorerLink } from "lib/components/ExplorerLink"; -import { Loading } from "lib/components/Loading"; -import { SaveOrRemoveCodeModal } from "lib/components/modal"; -import { PermissionChip } from "lib/components/PermissionChip"; -import { DisconnectedState } from "lib/components/state"; -import { - TableContainer, - TableHeaderNoBorder, - TableRowNoBorder, - CodeNameCell, -} from "lib/components/table"; -import type { CodeInfo } from "lib/types"; -import { getCw2Info } from "lib/utils"; - -// Types of Table: Recent Codes / My Stored Codes / My Saved Codes -type TableType = "recent" | "stored" | "saved"; - -interface CodesTableProps { - type: TableType; - tableName: string; - codes: CodeInfo[]; - isSearching: boolean; - action?: ReactNode; - isLoading: boolean; -} - -interface CodesRowProps { - code: CodeInfo; -} - -interface OtherTBodyProps { - type: TableType; -} - -const TEMPLATE_COLUMNS = - "max(100px) minmax(300px, 1fr) minmax(220px, 1fr) max(120px) max(160px) minmax(320px, 0.75fr)"; - -const StateContainer = ({ children }: { children: ReactNode }) => ( - - {children} - -); - -const NotMatched = () => ( - - result not found - No matched codes found. - -); - -const Unconnected = () => ( - - - -); - -const Empty = ({ type }: OtherTBodyProps) => { - const renderEmptyText = () => { - switch (type) { - case "recent": - return "Most recent 100 code IDs will display here"; - case "saved": - return "Codes saved using Celatone will display here. Saved codes are stored locally on your device."; - case "stored": - return "Your uploaded Wasm files will display as My Stored Codes"; - default: - return ""; - } - }; - return ( - - {renderEmptyText()} - - ); -}; - -const CodeTableHead = () => ( - - Code ID - Code Name - CW2 Info - Contracts - Uploader - Permission - -); - -const CodeTableRow = ({ code }: CodesRowProps) => { - const navigate = useInternalNavigate(); - const goToCodeDetails = () => { - navigate({ pathname: `/code/${code.id}` }); - }; - const cw2Info = getCw2Info(code.cw2Contract, code.cw2Version); - - return ( - - - - - - - - - - {cw2Info ?? "N/A"} - - - - e.stopPropagation()} - cursor="text" - w="fit-content" - m="auto" - px={2} - > - {code.contractCount ?? "N/A"} - - - - - - - - - e.stopPropagation()}> - - - - - - - ); -}; - -const NormalRender = ({ - codes, - tableName, -}: Pick) => ( - - - {codes.map((code) => ( - - ))} - -); - -function CodesTable({ - type, - tableName, - codes, - action, - isSearching, - isLoading, -}: CodesTableProps) { - const { address } = useWallet(); - - const renderBody = () => { - if (!address && type === "stored") return ; - if (isLoading) return ; - if (codes.length === 0 && isSearching) return ; - if (codes.length === 0) return ; - return ; - }; - - return ( - - - {type !== "recent" && ( - - {tableName} - - )} - {action} - - {renderBody()} - - ); -} - -export default CodesTable; diff --git a/src/lib/pages/codes/components/MySavedCodesSection.tsx b/src/lib/pages/codes/components/MySavedCodesSection.tsx new file mode 100644 index 000000000..52bb7e8d8 --- /dev/null +++ b/src/lib/pages/codes/components/MySavedCodesSection.tsx @@ -0,0 +1,36 @@ +import { Box, Heading, HStack } from "@chakra-ui/react"; + +import { MySavedCodesTable } from "lib/components/table"; +import type { CodeInfo } from "lib/types"; + +import { SaveCodeButton } from "./SaveCodeButton"; + +interface MySavedCodesSectionProps { + codes: CodeInfo[]; + isLoading: boolean; + onRowSelect: (codeId: number) => void; + isSearching: boolean; +} + +export const MySavedCodesSection = ({ + codes, + isLoading, + onRowSelect, + isSearching, +}: MySavedCodesSectionProps) => ( + + + + My Saved Codes + + + + + +); diff --git a/src/lib/pages/codes/components/MyStoredCodesSection.tsx b/src/lib/pages/codes/components/MyStoredCodesSection.tsx new file mode 100644 index 000000000..51c9ccf5c --- /dev/null +++ b/src/lib/pages/codes/components/MyStoredCodesSection.tsx @@ -0,0 +1,39 @@ +import { Box, Heading, HStack } from "@chakra-ui/react"; + +import { MyStoredCodesTable } from "lib/components/table"; +import type { CodeInfo } from "lib/types"; + +import { UploadButton } from "./UploadButton"; + +interface MyStoredCodesSectionProps { + codes: CodeInfo[]; + isLoading: boolean; + onRowSelect: (codeId: number) => void; + disconnectedMessage: string; + isSearching: boolean; +} + +export const MyStoredCodesSection = ({ + codes, + isLoading, + onRowSelect, + disconnectedMessage, + isSearching, +}: MyStoredCodesSectionProps) => ( + + + + My Stored Codes + + + + + +); diff --git a/src/lib/pages/codes/components/SaveCodeButton.tsx b/src/lib/pages/codes/components/SaveCodeButton.tsx index e2fa2a312..d84a71926 100644 --- a/src/lib/pages/codes/components/SaveCodeButton.tsx +++ b/src/lib/pages/codes/components/SaveCodeButton.tsx @@ -1,7 +1,7 @@ import { CustomIcon } from "lib/components/icon"; import { SaveNewCodeModal } from "lib/components/modal/code/SaveNewCode"; -export default () => ( +export const SaveCodeButton = () => ( { +export const UploadButton = () => { const navigate = useInternalNavigate(); return ( - ) : ( - - ), - children: "Save Contract", - }} - /> - )} - {contractListInfo.isInfoEditable && ( - - - - - - , - children: "Edit list name", - }} - reroute - /> - , - children: "Remove list", - }} + + + + + + {contractListInfo.name} + + + {isInstantiatedByMe ? ( + + ) : ( + - - - )} - + ), + children: "Save Contract", + }} + /> + )} + {contractListInfo.isInfoEditable && ( + + + + + + , + children: "Edit list name", + }} + reroute + /> + , + children: "Remove list", + }} + /> + + + )} - + - + ); }); diff --git a/src/lib/pages/home/components/RecentlyViewContracts.tsx b/src/lib/pages/home/components/RecentlyViewContracts.tsx deleted file mode 100644 index cb10875fc..000000000 --- a/src/lib/pages/home/components/RecentlyViewContracts.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import { Heading, Box, Flex, Text } from "@chakra-ui/react"; - -import { ContractListTable } from "lib/components/select-contract"; -import type { Addr, ContractAddr } from "lib/types"; -import { getCurrentDate } from "lib/utils"; - -/* TODO: change data -> recently view contracts */ -const contracts = [ - { - contractAddress: - "terra18kw0z0nmpk9drz4qxq8y7xvh05tr7spyzja3rq" as ContractAddr, - name: "Deposit asset", - tags: ["deposit", "lending"], - instantiator: "terra18kw0z0nmpk9drz4qxq8y7xvh05tr7spyzja3rq" as Addr, - description: - "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque sed facilisis facilisis risus. Ut volutpat accumsan massa eget consequat, id egestas nulla.", - label: "label1", - created: getCurrentDate(), - }, - { - contractAddress: - "terra18kw0z0nmpk9drz4qxq8y7xvh05tr7spyzja3rq" as ContractAddr, - name: "Borrow asset", - tags: ["deposit", "lending", "borrow", "beeb", "margin"], - instantiator: "terra18kw0z0nmpk9drz4qxq8y7xvh05tr7spyzja3rq" as Addr, - description: "Lorem ipsum dolor id egestas nulla.", - label: "label2", - created: getCurrentDate(), - }, - { - contractAddress: - "terra18kw0z0nmpk9drz4qxq8y7xvh05tr7spyzja3rq" as ContractAddr, - name: "", - tags: ["deposit", "lending", "borrow", "margin"], - instantiator: "terra18kw0z0nmpk9drz4qxq8y7xvh05tr7spyzja3rq" as Addr, - description: "", - label: "label3", - created: getCurrentDate(), - }, - { - contractAddress: - "terra18kw0z0nmpk9drz4qxq8y7xvh05tr7spyzja3rq" as ContractAddr, - name: "Deposit asset to Lorem", - tags: [], - instantiator: "terra18kw0z0nmpk9drz4qxq8y7xvh05tr7spyzja3rq" as Addr, - description: - "Lorem ipsum dolor sit amet, consectetur adipiscing elit. id egestas nulla.", - label: "label4", - created: getCurrentDate(), - }, -]; -export const RecentlyViewContracts = () => ( - - - Recently Viewed Contracts - - {contracts && contracts.length ? ( - - ) : ( - - - Your recently viewed smart contracts will display here - - - )} - -); diff --git a/src/lib/pages/past-txs/components/PastTxRow.tsx b/src/lib/pages/past-txs/components/PastTxRow.tsx index 0b2b68ea7..db8772dd8 100644 --- a/src/lib/pages/past-txs/components/PastTxRow.tsx +++ b/src/lib/pages/past-txs/components/PastTxRow.tsx @@ -31,7 +31,7 @@ export const PastTxRow = ({ transition="all .25s ease-in-out" cursor={isAccordion ? "pointer" : "default"} > - + ( - Transaction Hash + Transaction Hash Messages Timestamp diff --git a/src/lib/pages/past-txs/index.tsx b/src/lib/pages/past-txs/index.tsx index 7bb7f7c16..9081a8044 100644 --- a/src/lib/pages/past-txs/index.tsx +++ b/src/lib/pages/past-txs/index.tsx @@ -1,5 +1,4 @@ import { - Box, Flex, Heading, Input, @@ -13,6 +12,7 @@ import { useEffect, useMemo } from "react"; import { useForm } from "react-hook-form"; import { CustomIcon } from "lib/components/icon"; +import PageContainer from "lib/components/PageContainer"; import { Pagination } from "lib/components/pagination"; import { usePaginator } from "lib/components/pagination/usePaginator"; import { TxFilterSelection } from "lib/components/TxFilterSelection"; @@ -106,34 +106,32 @@ const PastTxs = () => { }, [router.isReady]); return ( - <> - - - Past Transactions - - - - - - setValue("search", e.target.value)} - placeholder="Search with transaction hash or contract address" - h="full" - /> - - - - - + + Past Transactions + + + + + + setValue("search", e.target.value)} + placeholder="Search with transaction hash or contract address" + h="full" /> - + + + + + - + { onPageSizeChange={onPageSizeChange} /> )} - + ); }; diff --git a/src/lib/pages/public-project/components/table/code/PublicProjectCodeRow.tsx b/src/lib/pages/public-project/components/table/code/PublicProjectCodeRow.tsx index 93459cbea..d5d33e32a 100644 --- a/src/lib/pages/public-project/components/table/code/PublicProjectCodeRow.tsx +++ b/src/lib/pages/public-project/components/table/code/PublicProjectCodeRow.tsx @@ -1,4 +1,4 @@ -import { HStack, Grid, Text, Flex } from "@chakra-ui/react"; +import { HStack, Grid, Text } from "@chakra-ui/react"; import { useWallet } from "@cosmos-kit/react"; import { useInternalNavigate, getAddressTypeByLength } from "lib/app-provider"; @@ -6,19 +6,19 @@ import { InstantiateButton } from "lib/components/button"; import { ExplorerLink } from "lib/components/ExplorerLink"; import { SaveOrRemoveCodeModal } from "lib/components/modal"; import { PermissionChip } from "lib/components/PermissionChip"; -import { TableRowNoBorder } from "lib/components/table"; +import { TableRow } from "lib/components/table"; import { getCw2Info } from "lib/utils"; import type { PublicCodeInfo } from "./PublicProjectCodeTable"; interface CodeTableRowProps { publicCodeInfo: PublicCodeInfo; - templateColumn: string; + templateColumns: string; } export const PublicProjectCodeRow = ({ publicCodeInfo: { publicInfo, localInfo }, - templateColumn, + templateColumns, }: CodeTableRowProps) => { const navigate = useInternalNavigate(); const { currentChainName } = useWallet(); @@ -32,26 +32,24 @@ export const PublicProjectCodeRow = ({ return ( - + - - + + {publicInfo.name} - - + + {cw2Info ?? "N/A"} - - + + {publicInfo.contractCount} - - + + - - - - + + + + + e.stopPropagation()}> + - e.stopPropagation()}> - - - - - + + + ); }; diff --git a/src/lib/pages/public-project/components/table/code/PublicProjectCodeTable.tsx b/src/lib/pages/public-project/components/table/code/PublicProjectCodeTable.tsx index 864c4d206..e8f81b170 100644 --- a/src/lib/pages/public-project/components/table/code/PublicProjectCodeTable.tsx +++ b/src/lib/pages/public-project/components/table/code/PublicProjectCodeTable.tsx @@ -22,16 +22,17 @@ interface PublicProjectCodeTableProps { } const TEMPLATE_COLUMNS = - "max(80px) minmax(300px, 1fr) minmax(220px, 1fr) max(120px) max(160px) minmax(320px, 0.75fr)"; + "max(100px) minmax(250px, 1fr) minmax(200px, 1fr) max(100px) max(160px) 150px 180px"; const CodeTableHeader = () => ( - + Code ID Code Name CW2 Info - Contracts + Contracts Uploader Permission + ); @@ -95,7 +96,7 @@ export const PublicProjectCodeTable = observer( ))} diff --git a/src/lib/pages/public-project/components/table/contract/PublicProjectContractRow.tsx b/src/lib/pages/public-project/components/table/contract/PublicProjectContractRow.tsx index 2202dc654..38330ede3 100644 --- a/src/lib/pages/public-project/components/table/contract/PublicProjectContractRow.tsx +++ b/src/lib/pages/public-project/components/table/contract/PublicProjectContractRow.tsx @@ -18,13 +18,13 @@ import { AddToOtherListModal, SaveContractDetailsModal, } from "lib/components/modal"; -import { TableRowNoBorder } from "lib/components/table"; +import { TableRow } from "lib/components/table"; import type { PublicContractInfo } from "./PublicProjectContractTable"; interface ContractTableRowProps { publicContractInfo: PublicContractInfo; - templateColumn: string; + templateColumns: string; } // TODO - Revisit this style (exist in multiple places) @@ -39,7 +39,7 @@ const StyledIconButton = chakra(IconButton, { export const PublicProjectContractRow = ({ publicContractInfo, - templateColumn, + templateColumns, }: ContractTableRowProps) => { const navigate = useInternalNavigate(); const { currentChainName } = useWallet(); @@ -52,16 +52,14 @@ export const PublicProjectContractRow = ({ return ( - + - - + + {publicContractInfo.publicInfo.name} {publicContractInfo.publicInfo.description && ( )} - - + + - - + + - + ); }; diff --git a/src/lib/pages/public-project/components/table/contract/PublicProjectContractTable.tsx b/src/lib/pages/public-project/components/table/contract/PublicProjectContractTable.tsx index 1448a81e3..8a2cb97cb 100644 --- a/src/lib/pages/public-project/components/table/contract/PublicProjectContractTable.tsx +++ b/src/lib/pages/public-project/components/table/contract/PublicProjectContractTable.tsx @@ -86,7 +86,7 @@ export const PublicProjectContractTable = observer( ))} diff --git a/src/lib/pages/recent-codes/index.tsx b/src/lib/pages/recent-codes/index.tsx index 99c18859e..e4eff6c83 100644 --- a/src/lib/pages/recent-codes/index.tsx +++ b/src/lib/pages/recent-codes/index.tsx @@ -5,10 +5,13 @@ import type { ChangeEvent } from "react"; import { useEffect } from "react"; import { useForm } from "react-hook-form"; +import { useInternalNavigate } from "lib/app-provider"; import { FilterByPermission } from "lib/components/forms"; import InputWithIcon from "lib/components/InputWithIcon"; +import PageContainer from "lib/components/PageContainer"; +import { EmptyState } from "lib/components/state"; +import { CodesTable } from "lib/components/table"; import type { PermissionFilterValue } from "lib/hooks"; -import CodesTable from "lib/pages/codes/components/CodesTable"; import { AmpEvent, AmpTrack } from "lib/services/amplitude"; import { useRecentCodesData } from "./data"; @@ -20,6 +23,13 @@ interface RecentCodesState { const RecentCodes = observer(() => { const router = useRouter(); + const navigate = useInternalNavigate(); + const onRowSelect = (codeId: number) => + navigate({ + pathname: "/code/[codeId]", + query: { codeId }, + }); + const { watch, setValue } = useForm({ defaultValues: { permissionValue: "all", @@ -36,9 +46,11 @@ const RecentCodes = observer(() => { if (router.isReady) AmpTrack(AmpEvent.TO_RECENT_CODES); }, [router.isReady]); + const isSearching = !!keyword || permissionValue !== "all"; + return ( - - + + Recent Codes @@ -61,13 +73,22 @@ const RecentCodes = observer(() => { + } + onRowSelect={onRowSelect} /> - + ); }); diff --git a/src/lib/services/contractService.ts b/src/lib/services/contractService.ts index da464030b..3c5e361c8 100644 --- a/src/lib/services/contractService.ts +++ b/src/lib/services/contractService.ts @@ -154,35 +154,35 @@ export const useInstantiateDetailByContractQuery = ( }; export const useAdminByContractAddresses = ( - contractAddresses: Option + contractAddresses: ContractAddr[] ): UseQueryResult> => { const { indexerGraphClient } = useCelatoneApp(); - const queryFn = useCallback(async () => { - if (!contractAddresses) - throw new Error("No contract selected (useAdminByContractAddresses)"); - - return indexerGraphClient - .request(getAdminByContractAddressesQueryDocument, { - contractAddresses, - }) - .then(({ contracts }) => - contracts.reduce>( - (prev, contract) => ({ - ...prev, - [contract.address as ContractAddr]: contract.admin?.address as Addr, - }), - {} - ) - ); - }, [contractAddresses, indexerGraphClient]); + const queryFn = useCallback( + async () => + indexerGraphClient + .request(getAdminByContractAddressesQueryDocument, { + contractAddresses, + }) + .then(({ contracts }) => + contracts.reduce>( + (prev, contract) => ({ + ...prev, + [contract.address as ContractAddr]: contract.admin + ?.address as Addr, + }), + {} + ) + ), + [contractAddresses, indexerGraphClient] + ); return useQuery( ["admin_by_contracts", contractAddresses, indexerGraphClient], queryFn, { keepPreviousData: true, - enabled: !!contractAddresses, + enabled: contractAddresses.length > 0, } ); };