Skip to content

Commit

Permalink
Implementing ss58 convertion on AddressBook Crud operations
Browse files Browse the repository at this point in the history
  • Loading branch information
henrypalacios committed Jan 30, 2024
1 parent 51c2905 commit da46201
Show file tree
Hide file tree
Showing 12 changed files with 328 additions and 144 deletions.
129 changes: 129 additions & 0 deletions src/components/AddressBook/AddressBookItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import { Delete, Edit, TaskAlt } from "@mui/icons-material";
import { TableCell, TableRow, TextField, Typography } from "@mui/material";
import React, { useRef } from "react";

import CopyButton from "@/components/common/CopyButton";
import OpenNewTabButton from "@/components/common/OpenNewTabButton";
import SvgIconButton from "@/components/common/SvgIconButton";
import NetworkBadge from "@/components/NetworkBadge";
import { ChainExtended } from "@/config/chain";
import { AddressBookInput } from "@/domain/AddressBooks";
import { UseDeleteAddressBookReturn } from "@/hooks/addressBook/useDeleteAddressBook";
import { UseUpdateAddressBook } from "@/hooks/addressBook/useUpdateAddressBook";
import { useForm } from "@/hooks/useForm";
import useOnClickOutside from "@/hooks/useOnClickOutside";
import { useRecentlyClicked } from "@/hooks/useRecentlyClicked";
import { getExplorerUrl } from "@/utils/blockchain";
import { notEmpty, onlyAddress } from "@/utils/inputValidation";

interface Props {
addressBook: AddressBookInput;
chain: ChainExtended;
deleteAddressBookItem: UseDeleteAddressBookReturn["deleteAddressBook"];
updateAddressBookItem: UseUpdateAddressBook["updateAddressBook"];
}

export function AddressBookItem({
addressBook,
chain,
deleteAddressBookItem: deleteAddressBook,
updateAddressBookItem,
}: Props) {
const formRef = useRef<HTMLTableRowElement>(null);
const { register, handleSubmit, errors, values, setValue, isValid, touched } =
useForm(addressBook);
useOnClickOutside(formRef, () => setValue("isEditing", false), ["Escape"]);
const { recentlyClicked, ref: refSaveButton } = useRecentlyClicked(50000);
const network = chain.id;
const isEditing = values.isEditing;
const _isValid =
isValid && Object.values(touched).length > 0 && !recentlyClicked;

return (
<TableRow ref={formRef}>
{isEditing ? (
<>
<TableCell>
<TextField
required
id="name"
name="name"
label="Name"
{...register("name", [notEmpty])}
error={!!errors.name}
helperText={errors.name}
/>
</TableCell>
<TableCell>
<TextField
required
id="address"
name="address"
label="Address"
sx={{ minWidth: "33rem" }}
{...register("address", [notEmpty, onlyAddress])}
error={!!errors.address}
helperText={errors.address}
/>
</TableCell>
</>
) : (
<>
<TableCell>
<Typography variant="body1">{addressBook.name}</Typography>
</TableCell>
<TableCell>
<Typography variant="body1" component="span">
{addressBook.formattedAddress}
</Typography>{" "}
<CopyButton text={addressBook?.formattedAddress as string} />
<OpenNewTabButton
text={getExplorerUrl(network, addressBook.formattedAddress)}
/>
</TableCell>
</>
)}
<TableCell>
<NetworkBadge
logo={chain.logo.src}
description={chain.logo.alt}
logoSize={{ width: 16, height: 16 }}
name={chain.name}
showTooltip={false}
></NetworkBadge>
</TableCell>
<TableCell>
{isEditing ? (
<SvgIconButton
ref={refSaveButton}
initialToolTipText="Save"
icon={TaskAlt}
color={_isValid ? "success" : "default"}
onClick={() => {
setValue("isEditing", false);
updateAddressBookItem({
oldAddressBook: addressBook,
newAddressBook: values,
});
}}
type="submit"
isLoading={recentlyClicked}
/>
) : (
<>
<SvgIconButton
initialToolTipText="Edit"
icon={Edit}
onClick={() => setValue("isEditing", true)}
/>
<SvgIconButton
initialToolTipText="Delete"
icon={Delete}
onClick={() => deleteAddressBook(addressBook.address)}
/>
</>
)}
</TableCell>
</TableRow>
);
}
128 changes: 14 additions & 114 deletions src/components/AddressBook/AddressBookTable.tsx
Original file line number Diff line number Diff line change
@@ -1,56 +1,30 @@
import { Delete, Edit, TaskAlt } from "@mui/icons-material";
import {
Table,
TableBody,
TableCell,
TableHead,
TableRow,
TextField,
Typography,
} from "@mui/material";
import React, { useEffect, useState } from "react";
import React from "react";

import { getChain } from "@/config/chain";
import { AddressBookInput, AddressBookItemUi } from "@/domain/AddressBooks";
import { AddressBookItemUi } from "@/domain/AddressBooks";
import { useDeleteAddressBook } from "@/hooks/addressBook/useDeleteAddressBook";
import { useUpdateAddressBook } from "@/hooks/addressBook/useUpdateAddressBook";
import { addressBookToAddressBookInput } from "@/services/localDB/transformers";
import { ChainId } from "@/services/useink/types";
import { getExplorerUrl } from "@/utils/blockchain";

import CopyButton from "../common/CopyButton";
import OpenNewTabButton from "../common/OpenNewTabButton";
import SvgIconButton from "../common/SvgIconButton";
import NetworkBadge from "../NetworkBadge";
import { AddressBookItem } from "./AddressBookItem";

type Props = {
network: ChainId;
addressBookItems: AddressBookItemUi[];
};

const AddressBookTable = ({ network, addressBookItems }: Props) => {
const { updateAddressBook, handleChange } = useUpdateAddressBook();
const { updateAddressBook } = useUpdateAddressBook();
const { deleteAddressBook } = useDeleteAddressBook();
const [tempData, setTempData] = useState<AddressBookInput[]>([]);

useEffect(() => {
setTempData(
addressBookItems.map((item) => ({ ...item, isEditing: false }))
);
}, [addressBookItems]);

const editAddressBook = (address: string) => {
const tempData = addressBookItems as AddressBookInput[];
const obj = tempData?.map((element) => {
if (element.address === address) {
return {
...element,
isEditing: !element.isEditing,
};
}
return element;
});
setTempData(obj);
};
const chain = getChain(network);

return (
<>
Expand All @@ -64,89 +38,15 @@ const AddressBookTable = ({ network, addressBookItems }: Props) => {
</TableRow>
</TableHead>
<TableBody>
{tempData?.map((addressBook, index) => {
const chain = getChain(addressBook.networkId);
{addressBookItems?.map((addressBook) => {
return (
<TableRow key={index}>
{addressBook.isEditing ? (
<>
<TableCell>
<TextField
required
id="name"
name="name"
label="Required"
onChange={(e) => handleChange(e)}
defaultValue={addressBook.name}
/>
</TableCell>
<TableCell>
<TextField
required
id="address"
name="address"
label="Required"
onChange={(e) => handleChange(e)}
defaultValue={addressBook.formattedAddress}
sx={{ minWidth: "33rem" }}
/>
</TableCell>
</>
) : (
<>
<TableCell>
<Typography variant="body1">
{addressBook.name}
</Typography>
</TableCell>
<TableCell>
<Typography variant="body1" component="span">
{addressBook.formattedAddress}
</Typography>{" "}
<CopyButton
text={addressBook?.formattedAddress as string}
/>
<OpenNewTabButton
text={getExplorerUrl(
network,
addressBook.formattedAddress
)}
/>
</TableCell>
</>
)}
<TableCell>
<NetworkBadge
logo={chain.logo.src}
description={chain.logo.alt}
logoSize={{ width: 16, height: 16 }}
name={chain.name}
showTooltip={false}
></NetworkBadge>
</TableCell>
<TableCell>
{addressBook.isEditing ? (
<SvgIconButton
initialToolTipText="Save"
icon={TaskAlt}
onClick={() => updateAddressBook(addressBook.address)}
/>
) : (
<>
<SvgIconButton
initialToolTipText="Edit"
icon={Edit}
onClick={() => editAddressBook(addressBook.address)}
/>
<SvgIconButton
initialToolTipText="Delete"
icon={Delete}
onClick={() => deleteAddressBook(addressBook.address)}
/>
</>
)}
</TableCell>
</TableRow>
<AddressBookItem
key={addressBook.address}
addressBook={addressBookToAddressBookInput(addressBook)}
chain={chain}
deleteAddressBookItem={deleteAddressBook}
updateAddressBookItem={updateAddressBook}
/>
);
})}
</TableBody>
Expand Down
6 changes: 4 additions & 2 deletions src/components/TxTable/TransactionsHistory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,17 @@ import { SignatoriesAccount } from "@/domain/SignatoriesAccount";
import { useListTxHistory } from "@/hooks/transactions/useListTxHistory";

import { LoadingSkeleton } from "../common/LoadingSkeleton";
import { TxDetailItem } from "./TxDetailItem";
import { Props as TxDetailItemProps, TxDetailItem } from "./TxDetailItem";

interface Props {
interface Props extends Pick<TxDetailItemProps, "findInAddressBook"> {
xsignerAccount: SignatoriesAccount;
network: ChainId;
}

export const TransactionHistory: React.FC<Props> = ({
xsignerAccount,
network,
findInAddressBook,
}) => {
const { data } = useListTxHistory(xsignerAccount, network);

Expand All @@ -36,6 +37,7 @@ export const TransactionHistory: React.FC<Props> = ({
txData={txData}
threshold={xsignerAccount.threshold}
network={network}
findInAddressBook={findInAddressBook}
/>
);
})}
Expand Down
6 changes: 4 additions & 2 deletions src/components/TxTable/TransactionsQueueDetail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,17 @@ import { SignatoriesAccount } from "@/domain/SignatoriesAccount";
import { useMultisigContractPromise } from "@/hooks/contractPromise/useMultisigContractPromise";
import { useListTxQueue } from "@/hooks/transactions/useListTxQueue";

import { TxDetailItem } from "./TxDetailItem";
import { Props as TxDetailItemProps, TxDetailItem } from "./TxDetailItem";

interface Props {
interface Props extends Pick<TxDetailItemProps, "findInAddressBook"> {
xsignerAccount: SignatoriesAccount;
network: ChainId;
}

export const TransactionQueueDetail: React.FC<Props> = ({
xsignerAccount,
network,
findInAddressBook,
}) => {
const { data } = useListTxQueue(xsignerAccount, network);
const { multisigContractPromise } = useMultisigContractPromise(
Expand All @@ -41,6 +42,7 @@ export const TransactionQueueDetail: React.FC<Props> = ({
threshold={xsignerAccount.threshold}
network={network}
multisigContractPromise={multisigContractPromise.contract}
findInAddressBook={findInAddressBook}
/>
);
})}
Expand Down
11 changes: 9 additions & 2 deletions src/components/TxTable/TxDetailItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
TransactionProposedItemUi,
} from "@/domain/TransactionProposedItemUi";
import { TX_STATUS_TYPE, TX_TYPE } from "@/hooks/transactions/const";
import { UseSetInAddressBook } from "@/hooks/useSetInAddressBook";
import { formatDate, truncateAddress } from "@/utils/formatString";

import { TxDetails } from "./TxDetail";
Expand All @@ -34,7 +35,7 @@ const StyledGrid = styled(Grid)<GridProps>(() => ({
display: "flex",
}));

type Props = {
export type Props = Pick<UseSetInAddressBook, "findInAddressBook"> & {
txData: TransactionProposedItemUi;
threshold: number;
index?: number;
Expand Down Expand Up @@ -101,13 +102,16 @@ export const TxDetailItem = ({
threshold,
network,
multisigContractPromise,
findInAddressBook,
}: Props) => {
const date = formatDate(txData.creationTimestamp);

const [expandedIds, setExpandedIds] = useState<{ [key: string]: boolean }>(
{}
);
const expanded = !!expandedIds[txData.txId];
const recipient = txData.from ?? txData.to;
const nameFromAddressBook = recipient && findInAddressBook(recipient);

const handleChange =
(id: string) => (event: React.SyntheticEvent, isExpanded: boolean) => {
Expand Down Expand Up @@ -200,7 +204,10 @@ export const TxDetailItem = ({
>
<span>{txType}</span>
<span style={{ fontSize: "0.9rem" }}>
{txData.txMsg} : {truncateAddress(txData.from ?? txData.to, 9)}
{txData.txMsg} :{" "}
{nameFromAddressBook
? `${nameFromAddressBook} (${truncateAddress(recipient, 4)})`
: truncateAddress(recipient, 9)}
</span>
</Box>
</StyledGrid>
Expand Down
Loading

0 comments on commit da46201

Please sign in to comment.