// Copyright (c) 2020-2021 Drew Lemmy
// This file is part of KristWeb 2 under GPL-3.0.
// Full details: https://github.com/tmpim/KristWeb2/blob/master/LICENSE.txt
import { useState, useEffect, Dispatch, SetStateAction } from "react";
import { Table, TablePaginationConfig, Tag } from "antd";
import { useTranslation } from "react-i18next";
import { KristName } from "@api/types";
import { lookupNames, LookupNamesOptions, LookupNamesResponse } from "@api/lookup";
import {
useMalleablePagination, useTableHistory, useDateColumnWidth
} from "@utils/table";
import { useWallets } from "@wallets";
import { NameActions } from "./mgmt/NameActions";
import { useNameTableLock } from "./tableLock";
import { KristNameLink } from "@comp/names/KristNameLink";
import { ContextualAddress } from "@comp/addresses/ContextualAddress";
import { TransactionConciseMetadata } from "@comp/transactions/TransactionConciseMetadata";
import { DateTime } from "@comp/DateTime";
import Debug from "debug";
const debug = Debug("kristweb:names-table");
interface Props {
// Number used to trigger a refresh of the names listing
refreshingID?: number;
// Whether or not to sort by newest first by default
sortNew?: boolean;
addresses?: string[];
setError?: Dispatch<SetStateAction<Error | undefined>>;
setPagination?: Dispatch<SetStateAction<TablePaginationConfig>>;
}
export function NamesTable({ refreshingID, sortNew, addresses, setError, setPagination }: Props): JSX.Element {
const { t } = useTranslation();
const [loading, setLoading] = useState(true);
const [res, setRes] = useState<LookupNamesResponse>();
const { options, setOptions } = useTableHistory<LookupNamesOptions>({
orderBy: sortNew ? "registered" : "name",
order: sortNew ? "DESC" : "ASC"
});
const { paginationTableProps, hotkeys } = useMalleablePagination(
res, res?.names,
"names.tableTotal",
options, setOptions, setPagination
);
const dateColumnWidth = useDateColumnWidth();
// Used to change the actions depending on whether or not we own the name
const { walletAddressMap } = useWallets();
// Used to pause the table lookups when performing a bulk name edit
const locked = useNameTableLock();
// Fetch the names from the API, mapping the table options
useEffect(() => {
if (locked) {
debug("skipping name lookup; table locked");
return;
}
debug("looking up names for %s", addresses ? addresses.join(",") : "network");
setLoading(true);
lookupNames(addresses, options)
.then(setRes)
.catch(setError)
.finally(() => setLoading(false));
}, [locked, refreshingID, addresses, setError, options]);
debug("results? %b res.names.length: %d res.count: %d res.total: %d", !!res, res?.names?.length, res?.count, res?.total);
const tbl = <Table<KristName>
className="names-table"
size="small"
loading={loading}
dataSource={res?.names || []}
rowKey="name"
{...paginationTableProps}
rowClassName={name => name.unpaid > 0 ? "name-row-unpaid" : ""}
columns={[
// Name
{
title: t("names.columnName"),
dataIndex: "name", key: "name",
render: name => <KristNameLink name={name} />,
sorter: true,
defaultSortOrder: sortNew ? undefined : "ascend"
},
// Owner
{
title: t("names.columnOwner"),
dataIndex: "owner", key: "owner",
render: owner => owner && (
<ContextualAddress
className="names-table-address"
address={owner}
allowWrap
/>
),
sorter: true
},
// Original owner
{
title: t("names.columnOriginalOwner"),
dataIndex: "original_owner", key: "original_owner",
render: owner => owner && (
<ContextualAddress
className="names-table-address"
address={owner}
allowWrap
/>
),
sorter: true
},
// A record
{
title: t("names.columnARecord"),
dataIndex: "a", key: "a",
render: a => <TransactionConciseMetadata metadata={a} />,
sorter: true
},
// Unpaid blocks
{
title: t("names.columnUnpaid"),
dataIndex: "unpaid", key: "unpaid",
render: unpaid => unpaid > 0
? <Tag color="CornFlowerBlue">{unpaid.toLocaleString()}</Tag>
: <></>,
width: 50,
sorter: true
},
// Registered time
{
title: t("names.columnRegistered"),
dataIndex: "registered", key: "registered",
render: time => <DateTime date={time} />,
width: dateColumnWidth,
sorter: true,
defaultSortOrder: sortNew ? "descend" : undefined
},
// Updated time
{
title: t("names.columnUpdated"),
dataIndex: "updated", key: "updated",
render: time => <DateTime date={time} />,
width: dateColumnWidth,
sorter: true
},
// Actions
{
key: "actions",
width: 100, // Force it to be minimum size
render: (_, record) => (
<NameActions
name={record}
isOwn={!!walletAddressMap[record.owner]}
/>
)
}
]}
/>;
return <>
{tbl}
{hotkeys}
</>;
}