Skip to main content
Glama

mcp-google-sheets

index.tsx9.35 kB
import { useMutation } from '@tanstack/react-query'; import { ColumnDef } from '@tanstack/react-table'; import { t } from 'i18next'; import { Trash2, Plus, CheckIcon, Table2, UploadCloud, EllipsisVertical, } from 'lucide-react'; import { useMemo, useState } from 'react'; import { useNavigate } from 'react-router-dom'; import LockedFeatureGuard from '@/app/components/locked-feature-guard'; import { DashboardPageHeader } from '@/components/custom/dashboard-page-header'; import { PermissionNeededTooltip } from '@/components/custom/permission-needed-tooltip'; import { ConfirmationDeleteDialog } from '@/components/delete-dialog'; import { Button } from '@/components/ui/button'; import { Checkbox } from '@/components/ui/checkbox'; import { BulkAction, DataTable, RowDataWithActions, } from '@/components/ui/data-table'; import { DataTableColumnHeader } from '@/components/ui/data-table/data-table-column-header'; import { LoadingScreen } from '@/components/ui/loading-screen'; import { PushToGitDialog } from '@/features/git-sync/components/push-to-git-dialog'; import { ApTableActionsMenu } from '@/features/tables/components/ap-table-actions-menu'; import { tableHooks } from '@/features/tables/lib/table-hooks'; import { tablesApi } from '@/features/tables/lib/tables-api'; import { useAuthorization } from '@/hooks/authorization-hooks'; import { platformHooks } from '@/hooks/platform-hooks'; import { projectHooks } from '@/hooks/project-hooks'; import { useNewWindow } from '@/lib/navigation-utils'; import { formatUtils } from '@/lib/utils'; import { Permission, Table } from '@activepieces/shared'; const ApTablesPage = () => { const openNewWindow = useNewWindow(); const [selectedRows, setSelectedRows] = useState<Table[]>([]); const { data: project } = projectHooks.useCurrentProject(); const { platform } = platformHooks.useCurrentPlatform(); const userHasTableWritePermission = useAuthorization().checkAccess( Permission.WRITE_TABLE, ); const userHasPermissionToPushToGit = useAuthorization().checkAccess( Permission.WRITE_PROJECT_RELEASE, ); const { data, isLoading, refetch } = tableHooks.useTables(); const { mutate: createTable, isPending: isCreatingTable } = tableHooks.useCreateTable(); const navigate = useNavigate(); const columns: ColumnDef<RowDataWithActions<Table>, unknown>[] = [ { id: 'select', accessorKey: 'select', header: ({ table }) => ( <Checkbox checked={ table.getIsAllPageRowsSelected() || table.getIsSomePageRowsSelected() } variant="secondary" onCheckedChange={(value) => { const isChecked = !!value; table.toggleAllPageRowsSelected(isChecked); if (isChecked) { const allRows = table .getRowModel() .rows.map((row) => row.original); setSelectedRows(allRows); } else { setSelectedRows([]); } }} /> ), cell: ({ row }) => { const isChecked = selectedRows.some( (selectedRow) => selectedRow.id === row.original.id, ); return ( <Checkbox variant="secondary" checked={isChecked} onCheckedChange={(value) => { const isChecked = !!value; let newSelectedRows = [...selectedRows]; if (isChecked) { newSelectedRows.push(row.original); } else { newSelectedRows = newSelectedRows.filter( (selectedRow) => selectedRow.id !== row.original.id, ); } setSelectedRows(newSelectedRows); row.toggleSelected(!!value); }} /> ); }, }, { accessorKey: 'name', header: ({ column }) => ( <DataTableColumnHeader column={column} title={t('Name')} /> ), cell: ({ row }) => <div className="text-left">{row.original.name}</div>, }, { accessorKey: 'created', header: ({ column }) => ( <DataTableColumnHeader column={column} title={t('Created')} /> ), cell: ({ row }) => ( <div className="text-left"> {formatUtils.formatDate(new Date(row.original.created))} </div> ), }, { id: 'actions', cell: ({ row }) => { return ( <div onAuxClick={(e) => { e.stopPropagation(); }} onContextMenu={(e) => { e.stopPropagation(); }} onClick={(e) => { e.stopPropagation(); e.preventDefault(); }} className="flex items-center justify-end w-full" > <ApTableActionsMenu table={row.original} refetch={refetch}> <Button variant="ghost" size="icon"> <EllipsisVertical /> </Button> </ApTableActionsMenu> </div> ); }, }, ]; const bulkDeleteMutation = useMutation({ mutationFn: async (ids: string[]) => { await Promise.all(ids.map((id) => tablesApi.delete(id))); }, onSuccess: () => { refetch(); }, }); const bulkActions: BulkAction<Table>[] = useMemo( () => [ { render: (_, __) => ( <PermissionNeededTooltip hasPermission={userHasTableWritePermission}> <Button onClick={() => createTable({ name: t('New Table') })} className="flex items-center gap-2" disabled={!userHasTableWritePermission} > <Plus className="h-4 w-4" /> {t('New Table')} </Button> </PermissionNeededTooltip> ), }, { render: (_, resetSelection) => ( <div onClick={(e) => e.stopPropagation()}> <ConfirmationDeleteDialog title={t('Delete Tables')} showToast={false} message={t( 'Are you sure you want to delete the selected tables? This action cannot be undone.', )} entityName={t('table')} mutationFn={async () => { try { await bulkDeleteMutation.mutateAsync( selectedRows.map((row) => row.id), ); resetSelection(); setSelectedRows([]); } catch (error) { console.error('Error deleting tables:', error); } }} > {selectedRows.length > 0 && ( <Button className="w-full mr-2" size="sm" variant="destructive"> <Trash2 className="mr-2 w-4" /> {`${t('Delete')} (${selectedRows.length})`} </Button> )} </ConfirmationDeleteDialog> </div> ), }, { render: (_) => ( <div onClick={(e) => e.stopPropagation()}> <PermissionNeededTooltip hasPermission={userHasPermissionToPushToGit} > <PushToGitDialog type="table" tables={selectedRows}> {selectedRows.length > 0 && ( <Button className="w-full mr-2" size="sm" variant="outline"> <UploadCloud className="mr-2 w-4" /> {`${t('Push to Git')} (${selectedRows.length})`} </Button> )} </PushToGitDialog> </PermissionNeededTooltip> </div> ), }, ], [bulkDeleteMutation, selectedRows, userHasPermissionToPushToGit], ); if (isCreatingTable) { return <LoadingScreen mode="container" />; } return ( <LockedFeatureGuard featureKey="TABLES" locked={!platform.plan.tablesEnabled} lockTitle={t('Tables')} lockDescription={t( 'Create and manage your tables to store your automation data', )} > <div className="flex-col w-full gap-4"> <DashboardPageHeader description={t( 'Create and manage your tables to store your automation data', )} title={t('Tables')} tutorialTab="tables" ></DashboardPageHeader> <DataTable filters={[ { accessorKey: 'name', type: 'input', title: t('Name'), icon: CheckIcon, }, ]} emptyStateIcon={<Table2 className="size-14" />} emptyStateTextTitle={t('No tables have been created yet')} emptyStateTextDescription={t( 'Create a table to get started and start managing your automation data', )} columns={columns} page={data} isLoading={isLoading} onRowClick={(row, newWindow) => { const path = `/projects/${project.id}/tables/${row.id}`; if (newWindow) { openNewWindow(path); } else { navigate(path); } }} bulkActions={bulkActions} /> </div> </LockedFeatureGuard> ); }; ApTablesPage.displayName = 'ApTablesPage'; export { ApTablesPage };

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/activepieces/activepieces'

If you have feedback or need assistance with the MCP directory API, please join our Discord server