From a15743a7c50217e1dd2338f20737ada548a0d46c Mon Sep 17 00:00:00 2001 From: Wes McKinney Date: Wed, 18 Dec 2024 13:58:07 -0600 Subject: [PATCH] Use common rendering code path as table data cells for column names --- .../components/dataGridColumnHeader.css | 8 +++ .../components/dataGridColumnHeader.tsx | 6 +-- .../browser/components/columnSummaryCell.css | 4 ++ .../browser/components/columnSummaryCell.tsx | 6 ++- .../browser/components/tableDataCell.tsx | 53 ++++++++++++------- .../positronDataExplorer/common/utils.ts | 17 ------ 6 files changed, 53 insertions(+), 41 deletions(-) diff --git a/src/vs/workbench/browser/positronDataGrid/components/dataGridColumnHeader.css b/src/vs/workbench/browser/positronDataGrid/components/dataGridColumnHeader.css index d3169511241..4709afa9e85 100644 --- a/src/vs/workbench/browser/positronDataGrid/components/dataGridColumnHeader.css +++ b/src/vs/workbench/browser/positronDataGrid/components/dataGridColumnHeader.css @@ -84,6 +84,14 @@ font-weight: var(--positron-data-grid-column-header-title-font-weight); } +.data-grid-column-header +.content +.title-description +.title +.whitespace { + opacity: 50%; +} + .data-grid-column-header .content .title-description diff --git a/src/vs/workbench/browser/positronDataGrid/components/dataGridColumnHeader.tsx b/src/vs/workbench/browser/positronDataGrid/components/dataGridColumnHeader.tsx index d74e6aad8e3..ea013a7aeb0 100644 --- a/src/vs/workbench/browser/positronDataGrid/components/dataGridColumnHeader.tsx +++ b/src/vs/workbench/browser/positronDataGrid/components/dataGridColumnHeader.tsx @@ -17,7 +17,7 @@ import { selectionType } from '../utilities/mouseUtilities.js'; import { VerticalSplitter } from '../../../../base/browser/ui/positronComponents/splitters/verticalSplitter.js'; import { ColumnSelectionState } from '../classes/dataGridInstance.js'; import { usePositronDataGridContext } from '../positronDataGridContext.js'; -import { getDisplayedColumnName } from '../../../services/positronDataExplorer/common/utils.js'; +import { renderLeadingTrailingWhitespace } from '../../../services/positronDataExplorer/browser/components/tableDataCell.js'; /** * Constants. @@ -104,7 +104,7 @@ export const DataGridColumnHeader = (props: DataGridColumnHeaderProps) => { // Determine whether the column is selected. const selected = (columnSelectionState & ColumnSelectionState.Selected) !== 0; - const displayedColumnName = getDisplayedColumnName(props.column?.name); + const renderedColumn = renderLeadingTrailingWhitespace(props.column?.name); // Render. return ( @@ -140,7 +140,7 @@ export const DataGridColumnHeader = (props: DataGridColumnHeaderProps) => { }} >
-
{displayedColumnName}
+
{renderedColumn}
{props.column?.description &&
{props.column.description}
} diff --git a/src/vs/workbench/services/positronDataExplorer/browser/components/columnSummaryCell.css b/src/vs/workbench/services/positronDataExplorer/browser/components/columnSummaryCell.css index 58a5fcddb2f..c48d06d350a 100644 --- a/src/vs/workbench/services/positronDataExplorer/browser/components/columnSummaryCell.css +++ b/src/vs/workbench/services/positronDataExplorer/browser/components/columnSummaryCell.css @@ -91,6 +91,10 @@ grid-column: title / sparkline; } +.data-grid-row-cell .content .column-summary .basic-info .column-name .whitespace { + opacity: 50%; +} + /* column-sparkline */ .data-grid-row-cell .content .column-summary .basic-info .column-sparkline { diff --git a/src/vs/workbench/services/positronDataExplorer/browser/components/columnSummaryCell.tsx b/src/vs/workbench/services/positronDataExplorer/browser/components/columnSummaryCell.tsx index 0a4103f8b10..c7f4783cc96 100644 --- a/src/vs/workbench/services/positronDataExplorer/browser/components/columnSummaryCell.tsx +++ b/src/vs/workbench/services/positronDataExplorer/browser/components/columnSummaryCell.tsx @@ -24,7 +24,7 @@ import { ColumnProfileDatetime } from './columnProfileDatetime.js'; import { TableSummaryDataGridInstance } from '../tableSummaryDataGridInstance.js'; import { ColumnDisplayType, ColumnProfileType, ColumnSchema } from '../../../languageRuntime/common/positronDataExplorerComm.js'; import { dataExplorerExperimentalFeatureEnabled } from '../../common/positronDataExplorerExperimentalConfig.js'; -import { getDisplayedColumnName } from '../../common/utils.js'; +import { renderLeadingTrailingWhitespace } from './tableDataCell.js'; /** * Constants. @@ -355,6 +355,8 @@ export const ColumnSummaryCell = (props: ColumnSummaryCellProps) => { break; } + const renderedColumn = renderLeadingTrailingWhitespace(props.columnSchema.column_name); + // Determine whether this is the cursor. const cursor = props.columnIndex === props.instance.cursorRowIndex; @@ -414,7 +416,7 @@ export const ColumnSummaryCell = (props: ColumnSummaryCellProps) => { onMouseLeave={() => props.hoverService.hideHover()} />
- {getDisplayedColumnName(props.columnSchema.column_name)} + {renderedColumn}
{!expanded && } diff --git a/src/vs/workbench/services/positronDataExplorer/browser/components/tableDataCell.tsx b/src/vs/workbench/services/positronDataExplorer/browser/components/tableDataCell.tsx index 809ae0e94f1..76c046cde43 100644 --- a/src/vs/workbench/services/positronDataExplorer/browser/components/tableDataCell.tsx +++ b/src/vs/workbench/services/positronDataExplorer/browser/components/tableDataCell.tsx @@ -23,33 +23,28 @@ interface TableDataCellProps { dataCell: DataCell; } -/** - * TableDataCell component. - * @param props A TableDataCellProps that contains the component properties. - * @returns The rendered component. - */ -export const TableDataCell = (props: TableDataCellProps) => { - const EMPTY_SPACE_SYMBOL = '\u00B7'; +export function renderLeadingTrailingWhitespace(text: string | undefined) { + const parts: (string | JSX.Element)[] = []; - let isSpecialValue = props.dataCell.kind !== DataCellKind.NON_NULL; + text = text ?? ''; - // Render empty strings as special value - // Initialize rendered output parts - const parts: (string | JSX.Element)[] = []; - const formattedText = props.dataCell.formatted - .replace(/\r/g, '\\r') - .replace(/\n/g, '\\n'); + if (text === '') { + // TODO: is this what we want? + return [{''}]; + } + + const EMPTY_SPACE_SYMBOL = '\u00B7'; // Handle text that is only whitespace - if (formattedText.trim() === '') { + if (text.trim() === '') { parts.push( - {EMPTY_SPACE_SYMBOL.repeat(formattedText.length)} + {EMPTY_SPACE_SYMBOL.repeat(text.length)} ); } else { // Handle leading whitespace - const leadingMatch = formattedText.match(/^\s+/); + const leadingMatch = text.match(/^\s+/); if (leadingMatch) { parts.push( @@ -59,11 +54,11 @@ export const TableDataCell = (props: TableDataCellProps) => { } // Add the main content - const mainContent = formattedText.trim(); + const mainContent = text.trim(); parts.push(mainContent); // Handle trailing whitespace - const trailingMatch = formattedText.match(/\s+$/); + const trailingMatch = text.match(/\s+$/); if (trailingMatch) { parts.push( @@ -72,6 +67,26 @@ export const TableDataCell = (props: TableDataCellProps) => { ); } } + + return parts; +} + +/** + * TableDataCell component. + * @param props A TableDataCellProps that contains the component properties. + * @returns The rendered component. + */ +export const TableDataCell = (props: TableDataCellProps) => { + // Render empty strings as special value + // Initialize rendered output parts + const formattedText = props.dataCell.formatted + .replace(/\r/g, '\\r') + .replace(/\n/g, '\\n'); + + const parts = renderLeadingTrailingWhitespace(formattedText); + + let isSpecialValue = props.dataCell.kind !== DataCellKind.NON_NULL; + let renderedOutput = parts; if (props.dataCell.kind === DataCellKind.NON_NULL && formattedText === '') { isSpecialValue = true; diff --git a/src/vs/workbench/services/positronDataExplorer/common/utils.ts b/src/vs/workbench/services/positronDataExplorer/common/utils.ts index 1f35b5d9844..db92c73ea0a 100644 --- a/src/vs/workbench/services/positronDataExplorer/common/utils.ts +++ b/src/vs/workbench/services/positronDataExplorer/common/utils.ts @@ -30,20 +30,3 @@ export const arrayFromIndexRange = (startIndex: number, endIndex: number) => export const linearConversion = (value: number, from: Range, to: Range) => ((value - from.min) / (from.max - from.min)) * (to.max - to.min) + to.min; - -/** - * Add quoting to column name in case it is an empty string or contains leading whitespace. - * @param name The column name from the backend - * @returns A modified column name that helps distinguish whitespace - */ -export function getDisplayedColumnName(name: string | undefined) { - let result = name ?? ''; - - const EMPTY_SPACE_SYMBOL = '\u2423'; - // If a column name is an empty string (allowed by pandas, at least) or contains - // leading whitespace, then we surround the column name with quotations. - if (result === '' || result.match(/^\s/)) { - result = `"${result}"`.replace(/ /g, EMPTY_SPACE_SYMBOL); - } - return result; -}