diff --git a/src/Explorer/Tabs/DocumentsTabV2/DocumentsTabV2.tsx b/src/Explorer/Tabs/DocumentsTabV2/DocumentsTabV2.tsx index 258ffcc87..c63050c4f 100644 --- a/src/Explorer/Tabs/DocumentsTabV2/DocumentsTabV2.tsx +++ b/src/Explorer/Tabs/DocumentsTabV2/DocumentsTabV2.tsx @@ -1,5 +1,5 @@ import { ItemDefinition, QueryIterator, Resource } from '@azure/cosmos'; -import { FluentProvider, Table, TableBody, TableCell, TableCellLayout, TableColumnDefinition, TableHeader, TableHeaderCell, TableRow, TableRowId, TableSelectionCell, createTableColumn, useArrowNavigationGroup, useTableFeatures, useTableSelection } from '@fluentui/react-components'; +import { FluentProvider } from '@fluentui/react-components'; import Split from '@uiw/react-split'; import { KeyCodes, QueryCopilotSampleContainerId, QueryCopilotSampleDatabaseId } from "Common/Constants"; import { getErrorMessage, getErrorStack } from 'Common/ErrorHandlingUtils'; @@ -25,11 +25,7 @@ import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcesso import * as QueryUtils from "../../../Utils/QueryUtils"; import DocumentId from "../../Tree/DocumentId"; import TabsBase from "../TabsBase"; - -type Item = { - id: string; - type: string; -}; +import { DocumentsTableComponent, DocumentsTableComponentItem } from "./DocumentsTableComponent"; export class DocumentsTabV2 extends TabsBase { public partitionKey: DataModels.PartitionKey; @@ -98,6 +94,9 @@ const DocumentsTabComponent: React.FunctionComponent<{ const [isExecutionError, setIsExecutionError] = useState(false); const [onLoadStartKey, setOnLoadStartKey] = useState(props.onLoadStartKey); + + const [currentDocument, setCurrentDocument] = useState(undefined); + // TODO remove this? const applyFilterButton = { enabled: true, @@ -423,119 +422,25 @@ const DocumentsTabComponent: React.FunctionComponent<{ props.collection?.databaseId === QueryCopilotSampleDatabaseId && props.collection?.id() === QueryCopilotSampleContainerId; - /* Below is for the table config */ - const items = documentIds.map((documentId) => ({ + + // Table config here + const tableItems: DocumentsTableComponentItem[] = documentIds.map((documentId) => ({ id: documentId.id(), // TODO: for now, merge all the pk values into a single string/column type: documentId.partitionKeyProperties ? documentId.stringPartitionKeyValues.join(",") : undefined, })); - const columns: TableColumnDefinition[] = [ - createTableColumn({ - columnId: "id", - compare: (a, b) => { - return a.id.localeCompare(b.id); - }, - renderHeaderCell: () => { - return "id"; - }, - renderCell: (item) => { - return ( - {item.id} - ); - }, - }), - createTableColumn({ - columnId: "type", - compare: (a, b) => { - return a.type.localeCompare(b.type); - }, - renderHeaderCell: () => { - return "/type"; - }, - renderCell: (item) => { - return ( - {item.type} - ); - }, - }), - ]; - const [selectedRows, setSelectedRows] = React.useState>( - () => new Set([0]) - ); - const { - getRows, - selection: { - allRowsSelected, - someRowsSelected, - toggleAllRows, - toggleRow, - isRowSelected, - }, - } = useTableFeatures( - { - columns, - items, - }, - [ - useTableSelection({ - selectionMode: "multiselect", - selectedItems: selectedRows, - onSelectionChange: (e, data) => setSelectedRows(data.selectedItems), - }), - ] - ); + const onSelectedDocument = (index: number) => readSingleDocument(documentIds[index]); - const rows = getRows((row) => { - const selected = isRowSelected(row.rowId); - return { - ...row, - onClick: (e: React.MouseEvent) => toggleRow(e, row.rowId), - onKeyDown: (e: React.KeyboardEvent) => { - if (e.key === " ") { - e.preventDefault(); - toggleRow(e, row.rowId); - } - }, - selected, - appearance: selected ? ("brand" as const) : ("none" as const), - }; - }); - - const toggleAllKeydown = React.useCallback( - (e: React.KeyboardEvent) => { - if (e.key === " ") { - toggleAllRows(e); - e.preventDefault(); - } - }, - [toggleAllRows] - ); - - const [currentDocument, setCurrentDocument] = useState(undefined); - - // Load document depending on selection - useEffect(() => { - if (selectedRows.size === 1 && documentIds.length > 0) { - const documentId = documentIds[selectedRows.values().next().value]; - - // TODO: replicate logic of selectedDocument.click(); - // TODO: Check if editor is dirty - - (_isQueryCopilotSampleContainer - ? readSampleDocument(documentId) - : readDocument(props.collection, documentId)).then((content) => { - // this.initDocumentEditor(documentId, content); - setCurrentDocument(content); - }); - } - }, [selectedRows, documentIds]); - - // Cell keyboard navigation - const keyboardNavAttr = useArrowNavigationGroup({ axis: "grid" }); - - /* End of table config */ + // TODO: replicate logic of selectedDocument.click(); + // TODO: Check if editor is dirty + const readSingleDocument = (documentId: DocumentId) => (_isQueryCopilotSampleContainer + ? readSampleDocument(documentId) + : readDocument(props.collection, documentId)).then((content) => { + // this.initDocumentEditor(documentId, content); + setCurrentDocument(content); + }); return
- - - - - id - /type - - - - {rows.map(({ item, selected, onClick, onKeyDown, appearance }, index: number) => ( - - - setSelectedRows(new Set([index]))} onKeyDown={onKeyDown}> - {item.id} - - - {item.type} - - - ))} - -
- +
{JSON.stringify(currentDocument, undefined, " ")}
diff --git a/src/Explorer/Tabs/DocumentsTabV2/DocumentsTableComponent.tsx b/src/Explorer/Tabs/DocumentsTabV2/DocumentsTableComponent.tsx new file mode 100644 index 000000000..c0f204abe --- /dev/null +++ b/src/Explorer/Tabs/DocumentsTabV2/DocumentsTableComponent.tsx @@ -0,0 +1,178 @@ +import { Table, TableBody, TableCell, TableCellLayout, TableColumnDefinition, TableHeader, TableHeaderCell, TableRow, TableRowId, TableSelectionCell, createTableColumn, useArrowNavigationGroup, useTableFeatures, useTableSelection } from '@fluentui/react-components'; +import React, { useEffect } from 'react'; + +export type DocumentsTableComponentItem = { + id: string; + type: string; +}; + +export interface IDocumentsTableComponentProps { + items: DocumentsTableComponentItem[]; + onSelectedItem: (index: number) => void; + style?: React.CSSProperties; +} + +export const DocumentsTableComponent: React.FC = ({ + items, onSelectedItem, style, +}: IDocumentsTableComponentProps) => { + const columns: TableColumnDefinition[] = [ + createTableColumn({ + columnId: "id", + compare: (a, b) => { + return a.id.localeCompare(b.id); + }, + renderHeaderCell: () => { + return "id"; + }, + renderCell: (item) => { + return ( + {item.id} + ); + }, + }), + createTableColumn({ + columnId: "type", + compare: (a, b) => { + return a.type.localeCompare(b.type); + }, + renderHeaderCell: () => { + return "/type"; + }, + renderCell: (item) => { + return ( + {item.type} + ); + }, + }), + ]; + + // const [columnSizingOptions] = React.useState({ + // id: { + // idealWidth: 300, + // minWidth: 150, + // }, + // type: { + // minWidth: 110, + // defaultWidth: 250, + // }, + // }); + + const [selectedRows, setSelectedRows] = React.useState>( + () => new Set([0]) + ); + + const { + getRows, + // columnSizing_unstable, + // tableRef, + selection: { + allRowsSelected, + someRowsSelected, + toggleAllRows, + toggleRow, + isRowSelected, + }, + } = useTableFeatures( + { + columns, + items, + }, + [ + // useTableColumnSizing_unstable({ columnSizingOptions }), + useTableSelection({ + selectionMode: "multiselect", + selectedItems: selectedRows, + onSelectionChange: (e, data) => setSelectedRows(data.selectedItems), + }), + ] + ); + + const rows = getRows((row) => { + const selected = isRowSelected(row.rowId); + return { + ...row, + onClick: (e: React.MouseEvent) => toggleRow(e, row.rowId), + onKeyDown: (e: React.KeyboardEvent) => { + if (e.key === " ") { + e.preventDefault(); + toggleRow(e, row.rowId); + } + }, + selected, + appearance: selected ? ("brand" as const) : ("none" as const), + }; + }); + + const toggleAllKeydown = React.useCallback( + (e: React.KeyboardEvent) => { + if (e.key === " ") { + toggleAllRows(e); + e.preventDefault(); + } + }, + [toggleAllRows] + ); + + // Load document depending on selection + useEffect(() => { + if (selectedRows.size === 1 && items.length > 0) { + onSelectedItem(selectedRows.values().next().value); + } + }, [selectedRows, items]); + + // Cell keyboard navigation + const keyboardNavAttr = useArrowNavigationGroup({ axis: "grid" }); + + const tableProps = { + "aria-label": "Filtered documents table", + role: "grid", + ...keyboardNavAttr, + // ...columnSizing_unstable.getTableProps(), + size: "extra-small", + // ref: tableRef, + ...style, + }; + + return ( + + + + + id + /type + + + + {rows.map(({ item, selected, onClick, onKeyDown, appearance }, index: number) => ( + + + setSelectedRows(new Set([index]))} onKeyDown={onKeyDown}> + {item.id} + + + {item.type} + + + ))} + +
+ ); +};