Skip to content

Commit

Permalink
refactor(authorization): use react-table for deployment grants
Browse files Browse the repository at this point in the history
refs #595
  • Loading branch information
ygrishajev committed Jan 2, 2025
1 parent e49cdc5 commit 3356ada
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 65 deletions.
3 changes: 2 additions & 1 deletion .commitlintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
"styling",
"observability",
"analytics",
"template"
"template",
"authorization"
]
]
}
Expand Down
2 changes: 1 addition & 1 deletion apps/deploy-web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
"@sentry/nextjs": "^8.30.0",
"@stripe/react-stripe-js": "^1.12.0",
"@stripe/stripe-js": "^1.41.0",
"@tanstack/react-table": "^8.13.2",
"@tanstack/react-table": "^8.20.6",
"@textea/json-viewer": "^3.0.0",
"auth0": "^4.3.1",
"axios": "^1.7.2",
Expand Down
168 changes: 114 additions & 54 deletions apps/deploy-web/src/components/authorizations/DeploymentGrantTable.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import React, { Dispatch, SetStateAction, useState } from "react";
import { Button, CustomPagination, Table, TableBody, TableHead, TableHeader, TableRow } from "@akashnetwork/ui/components";
import React, { Dispatch, SetStateAction } from "react";
import { FormattedTime } from "react-intl";
import { Address, Button, Checkbox, CustomPagination, Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@akashnetwork/ui/components";
import { createColumnHelper, flexRender, getCoreRowModel, useReactTable } from "@tanstack/react-table";
import { Bin, Edit } from "iconoir-react";

import { AKTAmount } from "@src/components/shared/AKTAmount";
import { GrantType } from "@src/types/grant";
import { coinToUDenom } from "@src/utils/priceUtils";
import { LinkTo } from "../shared/LinkTo";
import { GranterRow } from "./GranterRow";

interface Props {
grants: GrantType[];
Expand All @@ -14,13 +18,6 @@ interface Props {
}

export const DeploymentGrantTable: React.FC<Props> = ({ grants, onEditGrant, setDeletingGrants, setSelectedGrants, selectedGrants }) => {
const [pageIndex, setPageIndex] = useState(0);
const [pageSize, setPageSize] = useState<number>(10);
const start = pageIndex * pageSize;
const end = start + pageSize;
const currentPageGrants = grants.slice(start, end);
const pageCount = Math.ceil(grants.length / pageSize);

const onSelectGrant = (checked: boolean, grant: GrantType) => {
setSelectedGrants(prev => {
return checked ? prev.concat([grant]) : prev.filter(x => x.grantee !== grant.grantee);
Expand All @@ -43,55 +40,118 @@ export const DeploymentGrantTable: React.FC<Props> = ({ grants, onEditGrant, set
setSelectedGrants([]);
};

const handleChangePage = (newPage: number) => {
setPageIndex(newPage);
};
const columnHelper = createColumnHelper<GrantType>();

const onPageSizeChange = (value: number) => {
setPageSize(value);
setPageIndex(0);
};
const columns = [
columnHelper.accessor("grantee", {
header: () => <div>Grantee</div>,
cell: info => <Address address={info.getValue()} isCopyable />
}),
columnHelper.accessor(
row => {
return row.authorization.spend_limit;
},
{
id: "spendingLimit",
cell: info => {
const value = info.getValue();

return (
<div className="text-center">
<AKTAmount uakt={coinToUDenom(value)} /> {value.denom === "uakt" ? "AKT" : "USDC"}
</div>
);
},
header: () => <div className="text-center">Spending Limit</div>
}
),
columnHelper.accessor("expiration", {
header: () => <div className="text-center">Expiration</div>,
cell: info => (
<div className="text-center">
<FormattedTime year="numeric" month={"numeric"} day={"numeric"} value={info.getValue()} />
</div>
)
}),
columnHelper.display({
id: "actions",
header: () => (
<div className="w-1/4 text-center">
{selectedGrants.length > 0 && (
<div className="flex items-center justify-end space-x-4">
<LinkTo onClick={onClearSelection} className="text-xs">
Clear
</LinkTo>
<Button onClick={onDeleteGrants} variant="destructive" size="sm" className="h-6 p-2 text-xs">
Revoke selected ({selectedGrants.length})
</Button>
</div>
)}
{grants.length > 0 && selectedGrants.length === 0 && (
<div className="flex items-center justify-end">
<Button onClick={onDeleteAll} variant="destructive" size="sm" className="h-6 p-2 text-xs">
Revoke all
</Button>
</div>
)}
</div>
),
cell: info => {
const grant = info.row.original;

return (
<div className="flex items-center justify-end space-x-2">
<div className="flex w-[40px] items-center justify-center">
<Checkbox
onClick={event => {
event.stopPropagation();
}}
onCheckedChange={value => {
onSelectGrant(value as boolean, grant);
}}
/>
</div>
<Button variant="ghost" size="icon" onClick={() => onEditGrant(grant)}>
<Edit className="text-xs" />
</Button>
<Button variant="ghost" size="icon" onClick={() => onGrantDelete(grant)}>
<Bin className="text-xs" />
</Button>
</div>
);
}
})
];

const table = useReactTable({
data: grants,
columns,
getCoreRowModel: getCoreRowModel()
});
const pageCount = Math.ceil(grants.length / table.getState().pagination.pageSize);

return (
<div>
<Table>
<TableHeader>
<TableRow>
<TableHead className="w-1/4">Grantee</TableHead>
<TableHead className="w-1/4 text-center">Spending Limit</TableHead>
<TableHead className="w-1/4 text-center">Expiration</TableHead>
<TableHead className="w-1/4 text-center">
{selectedGrants.length > 0 && (
<div className="flex items-center justify-end space-x-4">
<LinkTo onClick={onClearSelection} className="text-xs">
Clear
</LinkTo>
<Button onClick={onDeleteGrants} variant="destructive" size="sm" className="h-6 p-2 text-xs">
Revoke selected ({selectedGrants.length})
</Button>
</div>
)}
{grants.length > 0 && selectedGrants.length === 0 && (
<div className="flex items-center justify-end">
<Button onClick={onDeleteAll} variant="destructive" size="sm" className="h-6 p-2 text-xs">
Revoke all
</Button>
</div>
)}
</TableHead>
</TableRow>
{table.getHeaderGroups().map(headerGroup => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map(header => (
<TableHead key={header.id} className="w-1/4">
{header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())}
</TableHead>
))}
</TableRow>
))}
</TableHeader>

<TableBody>
{currentPageGrants.map(grant => (
<GranterRow
key={grant.grantee}
grant={grant}
onEditGrant={onEditGrant}
setDeletingGrant={onGrantDelete}
onSelectGrant={onSelectGrant}
checked={selectedGrants.some(x => x.grantee === grant.grantee && x.granter === grant.granter)}
/>
{table.getRowModel().rows.map(row => (
<TableRow key={row.id}>
{row.getVisibleCells().map(cell => (
<TableCell key={cell.id}>{flexRender(cell.column.columnDef.cell, cell.getContext())}</TableCell>
))}
</TableRow>
))}
</TableBody>
</Table>
Expand All @@ -100,10 +160,10 @@ export const DeploymentGrantTable: React.FC<Props> = ({ grants, onEditGrant, set
<div className="flex items-center justify-center pt-6">
<CustomPagination
totalPageCount={pageCount}
setPageIndex={handleChangePage}
pageIndex={pageIndex}
pageSize={pageSize}
setPageSize={onPageSizeChange}
setPageIndex={table.setPageIndex}
pageIndex={table.getState().pagination.pageIndex}
pageSize={table.getState().pagination.pageSize}
setPageSize={table.setPageSize}
/>
</div>
)}
Expand Down
20 changes: 11 additions & 9 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 3356ada

Please sign in to comment.