diff --git a/packages/react/spec/auto/storybook/table/AutoTableActions.stories.jsx b/packages/react/spec/auto/storybook/table/AutoTableActions.stories.jsx index 6e2892cae..fb19bf8b3 100644 --- a/packages/react/spec/auto/storybook/table/AutoTableActions.stories.jsx +++ b/packages/react/spec/auto/storybook/table/AutoTableActions.stories.jsx @@ -61,6 +61,35 @@ export const NoTriggerableActions = { }, }; +export const CustomCellRenderersWithCustomActions = { + args: { + model: api.autoTableTest, + select: { + id: true, + str: true, + num: true, + email: true, + createdAt: true, + updatedAt: true, + }, + columns: [ + "id", + "str", + { + header: "custom cell renderer", + render: ({ record }) =>

{JSON.stringify(record)}

, + }, + ], + actions: [ + { + label: "console.log all records", + promoted: true, + action: (records) => console.log(`records:`, records), + }, + ], + }, +}; + const windowAlert = (message) => { // eslint-disable-next-line no-undef window.alert(message); diff --git a/packages/react/src/auto/hooks/useTableBulkActions.tsx b/packages/react/src/auto/hooks/useTableBulkActions.tsx index 4d663c0ec..16e61bc3e 100644 --- a/packages/react/src/auto/hooks/useTableBulkActions.tsx +++ b/packages/react/src/auto/hooks/useTableBulkActions.tsx @@ -1,3 +1,4 @@ +import { type GadgetRecord } from "@gadgetinc/api-client-core"; import React, { useCallback, useEffect, useMemo } from "react"; import deepEqual from "react-fast-compare"; import type { ActionCallback, TableOptions, TableRow } from "../../use-table/types.js"; @@ -175,13 +176,26 @@ const getValidatedBulkModelActionOption = (gadgetModelActionsAsBulkActionOptions return modelAction; }; -export const getBulkActionOptionCallback = (option: BulkActionOption, selectedRows: TableRow[], clearSelection: () => void) => - option.action +export const getBulkActionOptionCallback = (props: { + option: BulkActionOption; + selectedRows: TableRow[]; + clearSelection: () => void; + rawRecords: GadgetRecord[] | null; +}) => { + const { option, selectedRows, clearSelection, rawRecords } = props; + + const selectedRowsWithRawRecord = selectedRows.map((row) => ({ + ...(rawRecords?.find((record) => record.id === row.id) ?? {}), + ...row, + })); + + return option.action ? () => { - option.action?.(selectedRows); + option.action?.(selectedRowsWithRawRecord); clearSelection(); } : option.selectModelAction ?? (() => undefined); +}; export type AutoBulkActionModal = { model: any; diff --git a/packages/react/src/auto/polaris/PolarisAutoTable.tsx b/packages/react/src/auto/polaris/PolarisAutoTable.tsx index 8ab6defff..c91e923b4 100644 --- a/packages/react/src/auto/polaris/PolarisAutoTable.tsx +++ b/packages/react/src/auto/polaris/PolarisAutoTable.tsx @@ -174,13 +174,31 @@ const PolarisAutoTableComponent = < const selectedRows = (rows ?? []).filter((row) => selection.recordIds.includes(row.id as string)); const promotedBulkActions = useMemo( - () => bulkActionOptions.filter((option) => option.promoted).map(bulkActionOptionMapper(selectedRows, selection.clearAll)), - [bulkActionOptions, selectedRows] + () => + bulkActionOptions + .filter((option) => option.promoted) + .map( + bulkActionOptionMapper({ + rawRecords, + selectedRows, + clearSelection: selection.clearAll, + }) + ), + [bulkActionOptions, selectedRows, rawRecords, selection.clearAll] ); const bulkActions = useMemo( - () => bulkActionOptions.filter((option) => !option.promoted).map(bulkActionOptionMapper(selectedRows, selection.clearAll)), - [bulkActionOptions, selectedRows] + () => + bulkActionOptions + .filter((option) => !option.promoted) + .map( + bulkActionOptionMapper({ + rawRecords, + selectedRows, + clearSelection: selection.clearAll, + }) + ), + [bulkActionOptions, selectedRows, rawRecords, selection.clearAll] ); if (!error && ((fetching && !rows) || !columns)) { @@ -308,11 +326,15 @@ const disablePaginatedSelectAllButton = { paginatedSelectAllActionText: "", // Empty string to hide the select all button. We only allow selections on the current page. }; -const bulkActionOptionMapper = (selectedRows: TableRow[], clearSelection: () => void) => { +const bulkActionOptionMapper = (props: { + rawRecords: GadgetRecord[] | null; + selectedRows: TableRow[]; + clearSelection: () => void; +}) => { return (option: BulkActionOption) => ({ id: option.humanizedName, destructive: "isDeleter" in option ? option.isDeleter : false, content: option.humanizedName, - onAction: getBulkActionOptionCallback(option, selectedRows, clearSelection), + onAction: getBulkActionOptionCallback({ option, ...props }), }); }; diff --git a/packages/react/src/auto/shadcn/ShadcnAutoTable.tsx b/packages/react/src/auto/shadcn/ShadcnAutoTable.tsx index fe318df12..a91f3ecc5 100644 --- a/packages/react/src/auto/shadcn/ShadcnAutoTable.tsx +++ b/packages/react/src/auto/shadcn/ShadcnAutoTable.tsx @@ -302,7 +302,12 @@ export const makeAutoTable = (elements: ShadcnElements) => {
- +
)} diff --git a/packages/react/src/auto/shadcn/table/ShadcnAutoTableBulkActionSelector.tsx b/packages/react/src/auto/shadcn/table/ShadcnAutoTableBulkActionSelector.tsx index c5ab4d736..1824f18e8 100644 --- a/packages/react/src/auto/shadcn/table/ShadcnAutoTableBulkActionSelector.tsx +++ b/packages/react/src/auto/shadcn/table/ShadcnAutoTableBulkActionSelector.tsx @@ -1,3 +1,4 @@ +import { type GadgetRecord } from "@gadgetinc/api-client-core"; import { ChevronsUpDown } from "lucide-react"; import React, { useMemo } from "react"; import { type TableRow } from "../../../use-table/types.js"; @@ -12,8 +13,9 @@ export const makeShadcnAutoTableBulkActionSelector = (elements: ShadcnElements) nonPromotedActions: BulkActionOption[]; selection: RecordSelection; rows: TableRow[]; + rawRecords: GadgetRecord[] | null; }) { - const { nonPromotedActions, selection, rows } = props; + const { nonPromotedActions, selection, rows, rawRecords } = props; const selectedRows = rows.filter((row) => selection.recordIds.includes(row.id as string)); const [open, setOpen] = React.useState(false); @@ -45,7 +47,12 @@ export const makeShadcnAutoTableBulkActionSelector = (elements: ShadcnElements) key={i} className={"bg-background"} onSelect={() => { - getBulkActionOptionCallback(action, selectedRows, selection.clearAll)(); + getBulkActionOptionCallback({ + option: action, + selectedRows, + clearSelection: selection.clearAll, + rawRecords, + })(); }} > {action.humanizedName} @@ -59,8 +66,13 @@ export const makeShadcnAutoTableBulkActionSelector = (elements: ShadcnElements) ); } - function PromotedActionsActionSelector(props: { promotedActions: BulkActionOption[]; selection: RecordSelection; rows: TableRow[] }) { - const { promotedActions, selection, rows } = props; + function PromotedActionsActionSelector(props: { + promotedActions: BulkActionOption[]; + selection: RecordSelection; + rows: TableRow[]; + rawRecords: GadgetRecord[] | null; + }) { + const { promotedActions, selection, rows, rawRecords } = props; const selectedRows = rows.filter((row) => selection.recordIds.includes(row.id as string)); @@ -71,7 +83,12 @@ export const makeShadcnAutoTableBulkActionSelector = (elements: ShadcnElements) variant="outline" key={action.humanizedName} onClick={() => { - getBulkActionOptionCallback(action, selectedRows, selection.clearAll)(); + getBulkActionOptionCallback({ + option: action, + selectedRows, + clearSelection: selection.clearAll, + rawRecords, + })(); }} > {action.humanizedName} @@ -84,8 +101,9 @@ export const makeShadcnAutoTableBulkActionSelector = (elements: ShadcnElements) bulkActionOptions: BulkActionOption[]; selection: RecordSelection; rows: TableRow[]; + rawRecords: GadgetRecord[] | null; }) { - const { bulkActionOptions, selection, rows } = props; + const { bulkActionOptions, selection, rows, rawRecords } = props; const { promotedActions, nonPromotedActions } = useMemo(() => { const promotedActions = []; @@ -104,8 +122,13 @@ export const makeShadcnAutoTableBulkActionSelector = (elements: ShadcnElements) return ( <> - - + + ); }