Skip to main content
Glama

Convex MCP server

Official
by get-convex
DataRow.tsx8.56 kB
import { Value } from "convex/values"; import { GenericDocument } from "convex/server"; import React, { CSSProperties, memo, useCallback, useEffect, useMemo, useRef, useState, } from "react"; import { Row } from "react-table"; import classNames from "classnames"; import { useFirstMountState, usePrevious } from "react-use"; import { areEqual } from "react-window"; import { cn } from "@ui/cn"; import omit from "lodash/omit"; import { useContextMenuTrigger } from "@common/features/data/lib/useContextMenuTrigger"; import { Target } from "@common/features/data/components/ContextMenu"; import { useTableDensity } from "@common/features/data/lib/useTableDensity"; import { TableCheckbox } from "@common/features/data/components/Table/TableCheckbox"; import { DataCell, DataCellProps, } from "@common/features/data/components/Table/DataCell/DataCell"; import { usePatchDocumentField } from "@common/features/data/components/Table/utils/usePatchDocumentField"; import { arrowKeyHandler } from "@common/features/data/components/Table/utils/arrowKeyHandler"; import { toggleAdjacent } from "@common/features/data/components/Table/utils/toggleAdjacent"; import { SchemaJson } from "@common/lib/format"; type DataRowProps = { data: { areEditsAuthorized: boolean; isRowSelected(row: string): boolean; isSelectionAllNonExhaustive: boolean; resizingColumn: string | undefined; onAuthorizeEdits?(): void; patchDocument: ReturnType<typeof usePatchDocumentField>; prepareRow: (row: Row) => void; rows: Row[]; tableName: string; toggleIsRowSelected(key: string): void; onOpenContextMenu: DataCellProps["onOpenContextMenu"]; onCloseContextMenu: () => void; contextMenuRow: string | null; contextMenuColumn: string | null; canManageTable: boolean; activeSchema: SchemaJson | null; onEditDocument: (document: GenericDocument) => void; }; index: number; style: CSSProperties; }; export const DataRow = memo(DataRowImpl, areEqual); function DataRowImpl(props: DataRowProps) { const { data, index, style } = props; const firstRow = data.rows.length ? data.rows[0] : undefined; firstRow && data.prepareRow(firstRow); const { densityValues } = useTableDensity(); return index >= data.rows.length ? ( <div className="DataRow flex" style={{ ...style, height: densityValues.height }} > {firstRow ? ( firstRow.cells.map((cell, idx) => ( <div {...cell.getCellProps()} className={classNames("h-full flex items-center justify-center", { "border-r": cell !== firstRow.cells[firstRow.cells.length - 1], })} style={{ width: cell.getCellProps().style?.width, paddingTop: densityValues.paddingY, paddingBottom: densityValues.paddingY, paddingLeft: densityValues.paddingX, paddingRight: densityValues.paddingX, }} > <div className="h-4 bg-background-tertiary" style={{ width: idx === 0 ? "1rem" : "100%", }} /> </div> )) ) : ( <div className="mt-4 ml-4 h-4 w-full rounded-sm bg-neutral-8/20 dark:bg-neutral-3/20" /> )} </div> ) : ( <DataRowLoaded {...props} /> ); } export type EditingColumn = | { document: GenericDocument; column: string; editedValue: Value; } | undefined; function DataRowLoaded({ index, style, data }: DataRowProps) { const { areEditsAuthorized, isRowSelected, isSelectionAllNonExhaustive, onAuthorizeEdits, patchDocument, prepareRow, rows, tableName, toggleIsRowSelected, onOpenContextMenu, onCloseContextMenu, canManageTable, activeSchema, resizingColumn, onEditDocument, contextMenuColumn, contextMenuRow, } = data; const row: Row = rows[index]; const previousRow = usePrevious(row); const previousRows = usePrevious(rows); const didNumberOfRowsChange = previousRows?.length !== rows.length; const { _id } = row.values; const previousRowId = previousRow?.values._id; const [didJustCreate, setDidJustCreate] = useState(false); useEffect(() => { // The entire row should be highlighted if the row was recently created and // not already rendered. if (!previousRowId && Date.now() - row.values._creationTime < 1000) { setDidJustCreate(true); // To reset the animatation, reset the state after one second. setTimeout(() => setDidJustCreate(false), 1000); } }, [row, previousRow, previousRowId, _id]); const mounting = useFirstMountState(); const checked = isRowSelected(_id); prepareRow(row); // Context menu trigger for the checkbox cell const checkboxRef = useRef<HTMLLabelElement | null>(null); const contextMenuCallback = useCallback( (position: Target) => onOpenContextMenu(position, _id, null), [onOpenContextMenu, _id], ); useContextMenuTrigger(checkboxRef, contextMenuCallback, onCloseContextMenu); const document = useMemo(() => omit(row.values, "*select"), [row.values]); const editDocument = useCallback(() => { canManageTable && onEditDocument(document); }, [canManageTable, onEditDocument, document]); return ( <div className={classNames( // Make sure the focus ring is visible on first and last cell "focus:ring-none focus:border", didJustCreate && "animate-highlight", "DataRow", )} {...row.getRowProps({ style, })} key={row.getRowProps().key} > {row.cells.map((cell, columnIndex) => { const width = columnWidthToString(cell.getCellProps().style?.width); return ( <div {...cell.getCellProps({ style: { width } })} key={cell.getCellProps().key} className={cn( columnIndex < row.cells.length - 1 ? "border-r transition-colors duration-300" : "transition-colors duration-300", resizingColumn === (cell.column.Header as string) && "border-r-util-accent", )} > {columnIndex === 0 ? ( <TableCheckbox width={width} ref={checkboxRef} onKeyDown={arrowKeyHandler(checkboxRef)} isSelectionAllNonExhaustive={isSelectionAllNonExhaustive} onToggle={() => toggleIsRowSelected(_id)} onToggleAdjacent={() => toggleAdjacent( rows.map((r) => r.values._id), index, isRowSelected, toggleIsRowSelected, ) } checked={checked} /> ) : ( <DataCell activeSchema={activeSchema} rowId={_id} document={document} didRowChange={ // The row changed if it's already been mounted, // the previous row is not the same as the current row, // and the number of rows has not changed. !mounting && previousRowId !== _id && !didNumberOfRowsChange } areEditsAuthorized={areEditsAuthorized} onAuthorizeEdits={onAuthorizeEdits} editDocument={editDocument} value={cell.value} column={cell.column} width={width} inferIsDate={ (cell.column as unknown as { isDate: boolean }).isDate } patchDocument={patchDocument} tableName={tableName} onOpenContextMenu={onOpenContextMenu} onCloseContextMenu={onCloseContextMenu} isContextMenuOpen={ contextMenuColumn === (cell.column.Header as string) && contextMenuRow === _id } canManageTable={canManageTable} /> )} </div> ); })} </div> ); } // The goal here is to floor the width of the column to the nearest pixel to avoid // sub-pixel rendering issues in the browser. export const columnWidthToString = (width?: string | number) => width ? `${Math.floor( typeof width === "string" ? Number(width.replace("px", "")) : width, ).toString()}px` : `0px`;

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/get-convex/convex-backend'

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