From 469113d65c18a16e1e0c880c7d178bea3afa8c0f Mon Sep 17 00:00:00 2001 From: Yuru Shao Date: Sat, 28 Dec 2024 01:47:35 -0800 Subject: [PATCH] Add action buttons to products --- .../products/components/columns.tsx | 31 +++- .../components/data-table-pagination.tsx | 12 +- .../components/data-table-row-actions.tsx | 88 ++++++++-- .../products/components/data-table.tsx | 22 ++- .../playground/products/data/productSchema.ts | 3 +- .../playground/products/data/testProducts.tsx | 162 ------------------ .../(playground)/playground/products/page.tsx | 38 ++-- 7 files changed, 151 insertions(+), 205 deletions(-) delete mode 100644 playground/src/app/(playground)/playground/products/data/testProducts.tsx diff --git a/playground/src/app/(playground)/playground/products/components/columns.tsx b/playground/src/app/(playground)/playground/products/components/columns.tsx index af2a1e45..77fa07c6 100644 --- a/playground/src/app/(playground)/playground/products/components/columns.tsx +++ b/playground/src/app/(playground)/playground/products/components/columns.tsx @@ -7,7 +7,7 @@ import { Product } from "../data/productSchema"; import { DataTableColumnHeader } from "./data-table-column-header"; import { DataTableRowActions } from "./data-table-row-actions"; import { statuses } from "../data/data"; -import Sparkle from "../../../../../utils/Sparkle"; +import Sparkle from "@/utils/Sparkle"; import { Skeleton } from "@/components/ui/skeleton"; // Function to generate a random width within a range @@ -36,14 +36,14 @@ const VariableWidthSkeleton = ({ export const columns: ColumnDef[] = [ { - accessorKey: "imageKey", + accessorKey: "sparkleKey", header: ({ column }) => , cell: ({ row }) => (
{row.original.id.startsWith("skeleton-") ? ( ) : ( - + )}
), @@ -138,8 +138,25 @@ export const columns: ColumnDef[] = [ ), }, - // { - // id: "actions", - // cell: ({ row }) => , - // }, + { + accessorKey: "product", + header: ({ column }) => ( + + ), + cell: ({ row }) => ( +
+ {row.original.id.startsWith("skeleton-") ? ( + + ) : ( + +
{row.getValue("product")}
+
+ )} +
+ ), + }, + { + id: "actions", + cell: ({ row }) => , + }, ]; diff --git a/playground/src/app/(playground)/playground/products/components/data-table-pagination.tsx b/playground/src/app/(playground)/playground/products/components/data-table-pagination.tsx index 4eb8bc8a..a99d5787 100644 --- a/playground/src/app/(playground)/playground/products/components/data-table-pagination.tsx +++ b/playground/src/app/(playground)/playground/products/components/data-table-pagination.tsx @@ -25,8 +25,10 @@ export function DataTablePagination({ return (
- {/*{table.getFilteredSelectedRowModel().rows.length} of{" "} - {table.getFilteredRowModel().rows.length} row(s) selected.*/} + {/* + {table.getFilteredSelectedRowModel().rows.length} of{" "} + {table.getFilteredRowModel().rows.length} row(s) selected. + */}
@@ -75,7 +77,11 @@ export function DataTablePagination({ - Edit - Make a copy Favorite + { + e.preventDefault(); + e.stopPropagation(); + const next = + row.original.product === "Mint" + ? "/mint/access" + : "/vault/access"; + handleNavigation(next); + }} + > + Delegates + + + {["Vault", "Fund"].includes(row.original.product) ? ( + { + e.preventDefault(); + e.stopPropagation(); + handleNavigation("/vault/integrations"); + }} + > + Integrations + + + ) : null} - - Delete - ⌘⌫ + { + e.preventDefault(); + e.stopPropagation(); + close(row.original); + }} + > + Close + diff --git a/playground/src/app/(playground)/playground/products/components/data-table.tsx b/playground/src/app/(playground)/playground/products/components/data-table.tsx index ec7f034d..b511c6c2 100644 --- a/playground/src/app/(playground)/playground/products/components/data-table.tsx +++ b/playground/src/app/(playground)/playground/products/components/data-table.tsx @@ -13,6 +13,7 @@ import { getSortedRowModel, useReactTable, ColumnDef, + getPaginationRowModel, } from "@tanstack/react-table"; import { useRouter } from "next/navigation"; @@ -28,6 +29,7 @@ import { import { DataTableToolbar } from "./data-table-toolbar"; import { columns as defaultColumns } from "./columns"; import { Product } from "../data/productSchema"; +import { DataTablePagination } from "./data-table-pagination"; // Number of skeleton rows to display const SKELETON_ROW_COUNT = 10; @@ -47,7 +49,7 @@ export function DataTable({ const [columnVisibility, setColumnVisibility] = React.useState({}); const [columnFilters, setColumnFilters] = React.useState( - [] + [], ); const [sorting, setSorting] = React.useState([]); @@ -56,15 +58,20 @@ export function DataTable({ () => Array(SKELETON_ROW_COUNT) .fill(null) - .map((_, index) => ({ id: `skeleton-${index}` } as TData)), - [] + .map((_, index) => ({ id: `skeleton-${index}` }) as TData), + [], ); const tableData = React.useMemo( () => (isLoading || data.length === 0 ? skeletonData : data), - [isLoading, skeletonData, data] + [isLoading, skeletonData, data], ); + const [pagination, setPagination] = React.useState({ + pageIndex: 0, + pageSize: 10, + }); + const table = useReactTable({ data: tableData, columns, @@ -73,8 +80,11 @@ export function DataTable({ columnVisibility, rowSelection, columnFilters, + pagination, }, + onPaginationChange: setPagination, enableRowSelection: true, + getPaginationRowModel: getPaginationRowModel(), onRowSelectionChange: setRowSelection, onSortingChange: setSorting, onColumnFiltersChange: setColumnFilters, @@ -106,7 +116,7 @@ export function DataTable({ ? null : flexRender( header.column.columnDef.header, - header.getContext() + header.getContext(), )} ))} @@ -131,7 +141,7 @@ export function DataTable({
- {/**/} +
); } diff --git a/playground/src/app/(playground)/playground/products/data/productSchema.ts b/playground/src/app/(playground)/playground/products/data/productSchema.ts index 9c75a4ce..2bb64779 100644 --- a/playground/src/app/(playground)/playground/products/data/productSchema.ts +++ b/playground/src/app/(playground)/playground/products/data/productSchema.ts @@ -2,12 +2,13 @@ import { z } from "zod"; export const productSchema = z.object({ id: z.string(), - imageKey: z.string(), + sparkleKey: z.string(), name: z.string(), symbol: z.string(), baseAsset: z.string(), inception: z.string(), status: z.string(), + product: z.string(), }); export type Product = z.infer; diff --git a/playground/src/app/(playground)/playground/products/data/testProducts.tsx b/playground/src/app/(playground)/playground/products/data/testProducts.tsx deleted file mode 100644 index c71dfa6a..00000000 --- a/playground/src/app/(playground)/playground/products/data/testProducts.tsx +++ /dev/null @@ -1,162 +0,0 @@ -export const testProducts = [ - { - address: "GLAMvRgo7cHBPjQGf8UaVnsD6TUDjq16dEUuDPAPLjyJ", - name: "GLAM Alpha", - symbol: "GLAM", - baseAsset: "SOL", - inception: "2024-01-01", - status: "active", - }, - { - address: "GLAM5PUeNkEyM8wnxuwoHbGRqSVK6wWpfvTVxe2UJKR6", - name: "GLAM Beta", - symbol: "GLB", - baseAsset: "wETH", - inception: "2023-06-15", - status: "projected", - }, - { - address: "GLAMfixX32PwfCrHnkaMtXbHEYkUqvikSq73oSTat7UU", - name: "GLAM Gamma", - symbol: "GLG", - baseAsset: "wBTC", - inception: "2022-11-30", - status: "dormant", - }, - { - address: "GLAMmMgDGnRXY8GkVkwdEwWc2XpHiXronBUa2bfHAHik", - name: "GLAM Delta", - symbol: "GLD", - baseAsset: "USDT", - inception: "2023-01-20", - status: "inLiquidation", - }, - { - address: "GLAMz9bYh6tijKC3RUibwBTnj7H49EogWjN6c7c9r3kW", - name: "GLAM Epsilon", - symbol: "GLE", - baseAsset: "USDC", - inception: "2022-08-10", - status: "terminated", - }, - { - address: "GLAMDoSXvHbkzwJKEYVzVjZCz9ffeL9vT2ZqWGHpptHs", - name: "GLAM Zeta", - symbol: "GLZ", - baseAsset: "SOL", - inception: "2024-05-05", - status: "toBeLaunched", - }, - { - address: "GLAMHHNRp1ZzHHcBpppZB4sUjs8A2bo9kMS8MmWJLZsA", - name: "GLAM Eta", - symbol: "GLE", - baseAsset: "wETH", - inception: "2023-09-18", - status: "offeringPeriod", - }, - { - address: "GLAMV7SxVzCVeh41fDeKoi3EBigoBiApP4WcUGXrFAeL", - name: "GLAM Theta", - symbol: "GLT", - baseAsset: "wBTC", - inception: "2023-07-22", - status: "active", - }, - { - address: "GLAMofUq1HzDnrbk3jjdNu1Nx6fNzfgk8YxS9qKAyauK", - name: "GLAM Iota", - symbol: "GLI", - baseAsset: "USDT", - inception: "2023-10-01", - status: "projected", - }, - { - address: "GLAM2kWqEJviYV9LAkW2R3MHtSkYhuFXGH9PnCuBQ67F", - name: "GLAM Kappa", - symbol: "GLK", - baseAsset: "USDC", - inception: "2022-05-25", - status: "dormant", - }, - { - address: "GLAMonuafpMU9QVo2JFXvW2TSzFgBLLkyPEWaDCSmxYL", - name: "GLAM Lambda", - symbol: "GLL", - baseAsset: "SOL", - inception: "2023-03-15", - status: "inLiquidation", - }, - { - address: "GLAMm9QxSGEqWXFPCeAuhp2Y2YypbPS7zVKWViybvVA4", - name: "GLAM Mu", - symbol: "GLM", - baseAsset: "wETH", - inception: "2022-07-09", - status: "terminated", - }, - { - address: "GLAMxSh6Q296wnQ1dpJ9aL3WLz1j2YAJZLavXXNYJAVy", - name: "GLAM Nu", - symbol: "GLN", - baseAsset: "wBTC", - inception: "2024-02-14", - status: "toBeLaunched", - }, - { - address: "GLAMSScX26fRB7KRXU1wPYGHgdh6DvCa7TLxY87kKsj8", - name: "GLAM Xi", - symbol: "GLX", - baseAsset: "wBTC", - inception: "2023-11-11", - status: "offeringPeriod", - }, - { - address: "GLAM3DQTk4WygJxm4ApkMb4PjRxJoaxeXNYofBAYriqb", - name: "GLAM Omicron", - symbol: "GLO", - baseAsset: "USDC", - inception: "2022-03-28", - status: "active", - }, - { - address: "GLAMvBpQNGKLGCczVCHSVvPhHbhM9fmiHreKzwSDSPm9", - name: "GLAM Pi", - symbol: "GLP", - baseAsset: "SOL", - inception: "2023-05-05", - status: "projected", - }, - { - address: "GLAMAFB6xQQ22UcG6zP12bMVxpoCrnGMccEyA5Yw7uSc", - name: "GLAM Rho", - symbol: "GLR", - baseAsset: "wETH", - inception: "2023-12-01", - status: "dormant", - }, - { - address: "GLAMDbTxHN8dthijW6XQoWdnuF93frR1PrqC9UaV1Eov", - name: "GLAM Sigma", - symbol: "GLS", - baseAsset: "wBTC", - inception: "2022-09-15", - status: "inLiquidation", - }, - { - address: "GLAMGpeKYEgYujs8KEYsfWgRyoCPaJkTm3aF6s4FRSaP", - name: "GLAM Tau", - symbol: "GLT", - baseAsset: "wBTC", - inception: "2023-04-12", - status: "terminated", - }, - { - address: "GLAMC4L4Yz4VSif1jzxDBWMftkFWhqxKRXX4K7qG1C6t", - name: "GLAM Upsilon", - symbol: "GLU", - baseAsset: "SOL", - inception: "2024-03-22", - status: "toBeLaunched", - }, -]; diff --git a/playground/src/app/(playground)/playground/products/page.tsx b/playground/src/app/(playground)/playground/products/page.tsx index 5b46c8a5..0b95b834 100644 --- a/playground/src/app/(playground)/playground/products/page.tsx +++ b/playground/src/app/(playground)/playground/products/page.tsx @@ -2,9 +2,9 @@ import { DataTable } from "../products/components/data-table"; import { columns } from "../products/components/columns"; -import React from "react"; +import React, { useMemo } from "react"; import PageContentWrapper from "@/components/PageContentWrapper"; -import { useGlam } from "@glam/anchor/react"; +import { FundModel, useGlam } from "@glam/anchor/react"; export default function Products() { const { allFunds } = useGlam(); @@ -16,15 +16,31 @@ export default function Products() { } }, [allFunds]); - const products = (allFunds || []).map((f) => ({ - id: f.idStr, - imageKey: f.sparkleKey, - name: f.name || f.id?.toBase58() || "", - symbol: f.shareClasses[0]?.symbol || "-", - baseAsset: f.rawOpenfunds?.fundCurrency || "SOL", - inception: f.rawOpenfunds?.fundLaunchDate || "-", - status: "active", - })); + const getProduct = (f: FundModel) => { + if (f.shareClasses.length === 0) { + return "Vault"; + } + // @ts-ignore + if (f.integrationAcls.find((acl) => Object.keys(acl.name)[0] === "mint")) { + return "Mint"; + } + return "Fund"; + }; + + const products = useMemo( + () => + (allFunds || []).map((f) => ({ + id: f.idStr, + sparkleKey: f.sparkleKey, + name: f.name || f.idStr || "", + symbol: f.shareClasses[0]?.symbol || "-", + baseAsset: f.rawOpenfunds?.fundCurrency || "SOL", + inception: f.rawOpenfunds?.fundLaunchDate || "-", + status: "active", + product: getProduct(f), + })), + [allFunds], + ); return (