diff --git a/packages/components/releaseNotes/components.md b/packages/components/releaseNotes/components.md index 111de213b5..b79fa0f116 100644 --- a/packages/components/releaseNotes/components.md +++ b/packages/components/releaseNotes/components.md @@ -1,6 +1,12 @@ # @labkey/components Components, models, actions, and utility functions for LabKey applications and pages +### version 7.?.? +*Released*: ?? December 2025 +- GridColumn: remove width, fixedWidth properties + - Add css class for text align and getTextAlignClassName helper +- Grid: improve styling for columns + ### version 7.5.0 *Released*: 22 December 2025 - Chart builder updates for per-series line type option diff --git a/packages/components/src/index.ts b/packages/components/src/index.ts index bafbf59c72..64dba46034 100644 --- a/packages/components/src/index.ts +++ b/packages/components/src/index.ts @@ -22,7 +22,7 @@ import { hasParameter, imageURL, toggleParameter } from './internal/url/ActionUR import { encodeFormDataQuote } from './internal/url/utils'; import { Container } from './internal/components/base/models/Container'; import { hasAllPermissions, hasAnyPermissions, hasPermissions, User } from './internal/components/base/models/User'; -import { GridColumn } from './internal/components/base/models/GridColumn'; +import { getTextAlignClassName, GridColumn } from './internal/components/base/models/GridColumn'; import { decodePart, encodePart, getSchemaQuery, resolveKey, SchemaQuery } from './public/SchemaQuery'; import { insertColumnFilter, Operation, QueryColumn, QueryLookup } from './public/QueryColumn'; import { QuerySort } from './public/QuerySort'; @@ -1414,6 +1414,7 @@ export { Grid, GRID_CHECKBOX_OPTIONS, GridAliquotViewSelector, + getTextAlignClassName, GridColumn, GridPanel, GridPanelWithModel, diff --git a/packages/components/src/internal/components/__snapshots__/PreviewGrid.test.tsx.snap b/packages/components/src/internal/components/__snapshots__/PreviewGrid.test.tsx.snap index ebeea56e1f..2b303cab0e 100644 --- a/packages/components/src/internal/components/__snapshots__/PreviewGrid.test.tsx.snap +++ b/packages/components/src/internal/components/__snapshots__/PreviewGrid.test.tsx.snap @@ -34,7 +34,7 @@ exports[`PreviewGrid render PreviewGrid with data 1`] = ` class="grid-messages" /> @@ -47,7 +47,11 @@ exports[`PreviewGrid render PreviewGrid with data 1`] = ` If not provided, a unique name will be generated from the expression: null (Name)" > - Name +
+ Name +
@@ -83,120 +99,138 @@ null (Name)" class="grid-row-alternate" > @@ -221,7 +255,7 @@ exports[`PreviewGrid render PreviewGrid with different numCols and numRows 1`] = class="grid-messages" />
- Flag +
+ Flag +
- Mixture Type +
+ Mixture Type +
- Expiration Time +
+ Expiration Time +
- - DMEXP - + + DMEXP + + - - - Solution - + + Solution + + - 30 - +
- - TBS - + + TBS + + - - - Solution - + + Solution + + - 30 - +
- - PBS - + + PBS + + - - - Solution - + + Solution + + - 30 - +
@@ -234,7 +268,11 @@ exports[`PreviewGrid render PreviewGrid with different numCols and numRows 1`] = If not provided, a unique name will be generated from the expression: null (Name)" > - Name +
+ Name +
@@ -252,20 +294,23 @@ null (Name)" class="grid-row-alternate" > @@ -273,20 +318,23 @@ null (Name)" class="grid-row" > diff --git a/packages/components/src/internal/components/base/Grid.test.tsx b/packages/components/src/internal/components/base/Grid.test.tsx index d458466e1a..b5ed98bad1 100644 --- a/packages/components/src/internal/components/base/Grid.test.tsx +++ b/packages/components/src/internal/components/base/Grid.test.tsx @@ -153,55 +153,6 @@ describe('Grid', () => { expect(document.querySelector('.table-striped')).toBeNull(); }); - test('header title and calcWidths', () => { - render( - - ); - - expect(document.querySelector('.grid-header-cell').getAttribute('style')).toBe('min-width: 189px;'); - expect(document.querySelector('.grid-header-cell')).not.toBeNull(); - expect(document.querySelector('.phi-protected')).not.toBeNull(); - }); - - test('rendering with fixedWidth and width', () => { - const columns = List([ - { - index: 'name', - showHeader: true, - fixedWidth: 321, - width: 567, - }, - { - index: 'number', - showHeader: true, - width: 123, - }, - { - index: 'position', - showHeader: true, - fixedWidth: 567, - }, - ]); - render(); - const headerCells = document.querySelectorAll('.grid-header-cell'); - expect(headerCells).toHaveLength(3); - expect(headerCells[0].getAttribute('style')).toBe('width: 321px;'); - expect(headerCells[1].getAttribute('style')).toBe('min-width: 123px;'); - expect(headerCells[2].getAttribute('style')).toBe('width: 567px;'); - }); - test('render with messages', () => { render(); validateHasData(); diff --git a/packages/components/src/internal/components/base/Grid.tsx b/packages/components/src/internal/components/base/Grid.tsx index 2b970c9176..88c1e3d031 100644 --- a/packages/components/src/internal/components/base/Grid.tsx +++ b/packages/components/src/internal/components/base/Grid.tsx @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React, { CSSProperties, FC, Fragment, memo, PureComponent, ReactNode, RefObject } from 'react'; +import React, { FC, Fragment, memo, PureComponent, ReactNode, RefObject } from 'react'; import classNames from 'classnames'; import { fromJS, List, Map } from 'immutable'; @@ -22,7 +22,7 @@ import { HelpTipRenderer } from '../forms/HelpTipRenderer'; import { GRID_HEADER_CELL_BODY, GRID_SELECTION_INDEX } from '../../constants'; import { LabelHelpTip } from './LabelHelpTip'; -import { GridColumn } from './models/GridColumn'; +import { getTextAlignClassName, GridColumn } from './models/GridColumn'; function processColumns(columns: List): List { return columns @@ -44,11 +44,9 @@ function processColumns(columns: List): List { helpTipRenderer: c.helpTipRenderer, hideTooltip: c.helpTipRenderer !== undefined, index: c.index, - fixedWidth: c.fixedWidth, raw: c, tableCell: c.tableCell, title: c.title || c.caption, - width: c.width, }); }) .toList(); @@ -96,7 +94,6 @@ export function getColumnHoverText(info: any): string { } interface GridHeaderProps { - calcWidths?: boolean; columns: List; headerCell?: any; onColumnDrop?: (sourceIndex: string, targetIndex: string) => void; @@ -156,7 +153,7 @@ export class GridHeader extends PureComponent { }; render() { - const { calcWidths, columns, headerCell, showHeader, onColumnDrop } = this.props; + const { columns, headerCell, showHeader, onColumnDrop } = this.props; const { dragTarget } = this.state; if (!showHeader) { @@ -169,26 +166,9 @@ export class GridHeader extends PureComponent { {columns .map((column, i) => { - const { headerCls, index, fixedWidth, raw, title, width, hideTooltip } = column; + const { headerCls, index, raw, title, hideTooltip } = column; const draggable = onColumnDrop !== undefined; - let style: CSSProperties; - if (fixedWidth) { - style = { - width: `${fixedWidth}px`, - }; - } - - let colMinWidth = width; - if (colMinWidth === undefined) { - // the additional 45px is to account for the grid column header icons for sort/filter and the dropdown toggle - colMinWidth = calcWidths && title ? Math.max(45 + title.length * 8, 150) : undefined; - } - if (!fixedWidth && colMinWidth !== undefined) { - if (!style) style = {}; - style.minWidth = `${colMinWidth}px`; - } - if (column.showHeader) { const className = classNames(headerCls, { 'grid-header-cell': headerCls === undefined, @@ -211,20 +191,23 @@ export class GridHeader extends PureComponent { onDragOver={this.handleDragOver} onDragStart={this.handleDragStart} onDrop={this.handleDrop} - style={style} title={hideTooltip ? undefined : description} > - {headerCell ? headerCell(column, i, columns.size) : title} - {/* headerCell will render the helpTip, so only render here if not using headerCell() */} - {!headerCell && column.helpTipRenderer && ( - - - + {headerCell && headerCell(column, i, columns.size)} + {!headerCell && ( +
+ {title} + {column.helpTipRenderer && ( + + + + )} +
)} ); } - return
@@ -259,33 +242,36 @@ interface GridRowProps { rowIdx: number; } -const GridRow: FC = memo(({ columns, highlight, row, rowIdx }) => { - // style cast to "any" type due to @types/react@16.3.14 switch to csstype package usage which does not declare - // "textAlign" property correctly for - {columns - .map((column: GridColumn, c: number) => - column.tableCell ? ( +const GridRow: FC = memo(({ columns, highlight, row, rowIdx }) => ( + + {columns + .map((column: GridColumn, c: number) => { + if (column.tableCell) { + return ( {column.cell(row.get(column.index), row, column, rowIdx, c)} - ) : ( - - ) - ) - .toArray()} - - ); -}); + + + ); + }) + .toArray()} + +)); GridRow.displayName = 'GridRow'; interface EmptyGridRowProps { @@ -342,7 +328,6 @@ export type GridData = List> | Record[]; export interface GridProps { bordered?: boolean; - calcWidths?: boolean; cellular?: boolean; columns?: List; condensed?: boolean; @@ -370,7 +355,6 @@ export interface GridProps { export const Grid: FC = memo(props => { const { bordered = true, - calcWidths = false, cellular = false, condensed = false, data = List>(), @@ -393,7 +377,6 @@ export const Grid: FC = memo(props => { const gridData = processData(data); const gridColumns = columns !== undefined ? processColumns(columns) : resolveColumns(gridData); const headerProps: GridHeaderProps = { - calcWidths, columns: gridColumns, headerCell, onColumnDrop, @@ -410,7 +393,7 @@ export const Grid: FC = memo(props => { highlightRowIndexes, }; - const tableClasses = classNames({ + const tableClasses = classNames('read-only-table', { table: !cellular, 'table-cellular': cellular, 'table-striped': striped, diff --git a/packages/components/src/internal/components/base/models/GridColumn.tsx b/packages/components/src/internal/components/base/models/GridColumn.tsx index 20a58649c0..39b4c60e05 100644 --- a/packages/components/src/internal/components/base/models/GridColumn.tsx +++ b/packages/components/src/internal/components/base/models/GridColumn.tsx @@ -16,12 +16,10 @@ interface ColumnProps { helpTipRenderer?: string; hideTooltip?: boolean; index: string; - fixedWidth?: number; raw?: any; showHeader?: boolean; tableCell?: boolean; title: string; - width?: number; } const defaultCell: GridColumnCellRenderer = d => { @@ -56,23 +54,19 @@ export class GridColumn implements ColumnProps { helpTipRenderer?: string; hideTooltip?: boolean; index: string; - fixedWidth: number; raw: any; tableCell: boolean; title: string; showHeader: boolean; - width: number; constructor(config: ColumnProps) { this.align = config.align; this.cell = config.cell ?? defaultCell; this.format = config.format; this.index = config.index; - this.fixedWidth = config.fixedWidth; this.raw = config.raw; this.headerCls = config.headerCls; this.helpTipRenderer = config.helpTipRenderer; - this.width = config.width; // react render displays ' ', see: https://facebook.github.io/react/docs/jsx-gotchas.html if (config.title && config.title == ' ') { @@ -86,3 +80,18 @@ export class GridColumn implements ColumnProps { this.hideTooltip = config.hideTooltip === true; // defaults to false } } + +// Special interface that lets us pass GridColumn and QueryColumn to getTextAlignClassname +interface WithAlignment { + align?: string; +} + +const TEXT_ALIGN_CLASSES = { + center: 'text-center', + left: 'text-left', + right: 'text-right', +}; + +export function getTextAlignClassName(column: WithAlignment): string { + return TEXT_ALIGN_CLASSES[column?.align] ?? TEXT_ALIGN_CLASSES.left; +} diff --git a/packages/components/src/internal/components/domainproperties/DomainPropertiesGrid.tsx b/packages/components/src/internal/components/domainproperties/DomainPropertiesGrid.tsx index 3d390911e7..cbc2d3b1f2 100644 --- a/packages/components/src/internal/components/domainproperties/DomainPropertiesGrid.tsx +++ b/packages/components/src/internal/components/domainproperties/DomainPropertiesGrid.tsx @@ -194,6 +194,6 @@ export class DomainPropertiesGrid extends React.PureComponent; + return ; } } diff --git a/packages/components/src/internal/components/domainproperties/__snapshots__/DomainFieldsDisplay.test.tsx.snap b/packages/components/src/internal/components/domainproperties/__snapshots__/DomainFieldsDisplay.test.tsx.snap index d48fcde4f6..b8e15ba7bd 100644 --- a/packages/components/src/internal/components/domainproperties/__snapshots__/DomainFieldsDisplay.test.tsx.snap +++ b/packages/components/src/internal/components/domainproperties/__snapshots__/DomainFieldsDisplay.test.tsx.snap @@ -23,7 +23,7 @@ exports[`DomainFieldsDisplay with empty domain design 1`] = ` class="grid-messages" />
- Flag +
+ Flag +
- - DMEXP - + + DMEXP + + -
- - TBS - + + TBS + + -
; + return ; }, this) .toArray()}
elements. - return ( -
+ ); + } + + const className = getTextAlignClassName(column); + return ( + +
{column.cell(row.get(column.index), row, column, rowIdx, c)} -
@@ -32,42 +32,66 @@ exports[`DomainFieldsDisplay with empty domain design 1`] = ` draggable="false" id="name" > - Name +
+ Name +
@@ -114,7 +138,7 @@ exports[`DomainFieldsDisplay with title 1`] = ` class="grid-messages" />
- Label +
+ Label +
- Range URI +
+ Range URI +
- Concept URI +
+ Concept URI +
- Required +
+ Required +
- Scale +
+ Scale +
@@ -123,42 +147,66 @@ exports[`DomainFieldsDisplay with title 1`] = ` draggable="false" id="name" > - Name +
+ Name +
@@ -205,7 +253,7 @@ exports[`DomainFieldsDisplay without title 1`] = ` class="grid-messages" />
- Label +
+ Label +
- Range URI +
+ Range URI +
- Concept URI +
+ Concept URI +
- Required +
+ Required +
- Scale +
+ Scale +
@@ -214,42 +262,66 @@ exports[`DomainFieldsDisplay without title 1`] = ` draggable="false" id="name" > - Name +
+ Name +
diff --git a/packages/components/src/internal/components/domainproperties/models.tsx b/packages/components/src/internal/components/domainproperties/models.tsx index 50326689f3..67b8b21cb8 100644 --- a/packages/components/src/internal/components/domainproperties/models.tsx +++ b/packages/components/src/internal/components/domainproperties/models.tsx @@ -494,7 +494,6 @@ export class DomainDesign const selectionCol = new GridColumn({ index: GRID_SELECTION_INDEX, title: GRID_SELECTION_INDEX, - width: 20, cell: (data, row) => { const domainIndex = row.get('domainIndex'); const fieldIndex = row.get('fieldIndex'); diff --git a/packages/components/src/internal/components/editable/EditableGrid.tsx b/packages/components/src/internal/components/editable/EditableGrid.tsx index c37f4a25b7..df7b9426de 100644 --- a/packages/components/src/internal/components/editable/EditableGrid.tsx +++ b/packages/components/src/internal/components/editable/EditableGrid.tsx @@ -27,6 +27,7 @@ import { CELL_SELECTION_HANDLE_CLASSNAME, GRID_CHECKBOX_OPTIONS, GRID_EDIT_INDEX, + GRID_HEADER_CELL_BODY, GRID_SELECTION_INDEX, MAX_EDITABLE_GRID_ROWS, } from '../../constants'; @@ -98,10 +99,6 @@ function moveUp(colIdx: number, rowIdx: number): CellCoordinates { return { colIdx, rowIdx: rowIdx - 1 }; } -function hasCellWidthOverride(metadata: EditableColumnMetadata): boolean { - return !!metadata?.minWidth || !!metadata?.width; -} - function computeSelectionCellKeys( editorModel: EditorModel, minColIdx: number, @@ -144,12 +141,9 @@ const COUNT_COL = new GridColumn({ index: GRID_EDIT_INDEX, tableCell: true, title: 'Row', - width: 45, - // style cast to "any" type due to @types/react@16.3.14 switch to csstype package usage which does not declare - // "textAlign" property correctly for ), }); @@ -184,8 +178,6 @@ function inputCellFactory( const { isReadonlyCell, isReadonlyRow } = editorModel.getCellReadStatus(fieldKey, rowIdx, readonlyRows); const rowContainer = editorModel.getFolderValueForRow(rowIdx); const focused = editorModel.isFocused(colIdx, rowIdx); - const className = classNames({ 'grid-col-with-width': hasCellWidthOverride(columnMetadata) }); - const style = { textAlign: columnMetadata?.align ?? c.align ?? 'left' } as any; // If we're updating then we want to use the container path from each row if present if (forUpdate && rowContainer) containerPath = rowContainer; @@ -225,7 +217,7 @@ function inputCellFactory( } return ( -
- Label +
+ Label +
- Range URI +
+ Range URI +
- Concept URI +
+ Concept URI +
- Required +
+ Required +
- Scale +
+ Scale +
elements. cell: (d, r, c, rn) => ( - -
{rn + 1}
+
+ {rn + 1} + { const qCol = editorModel.columnMap.get(fieldKey); const metadata = editorModel.getColumnMetadata(qCol.fieldKey); - let width = 100; - let fixedWidth; - if (hasCellWidthOverride(metadata)) { - fixedWidth = metadata.width; - if (!fixedWidth) { - width = metadata.minWidth; - } - } const hideTooltip = metadata?.hideTitleTooltip ?? qCol.hasHelpTipData; gridColumns = gridColumns.push( new GridColumn({ @@ -878,10 +862,8 @@ export class EditableGrid extends PureComponent +
{!showLabelOverlay && ( <> {label} @@ -927,7 +909,7 @@ export class EditableGrid extends PureComponent )} - +
); }; @@ -1589,7 +1571,6 @@ export class EditableGrid extends PureComponent custom column headers 1`] = ` class="grid-messages" /> @@ -34,21 +34,33 @@ exports[` custom column headers 1`] = ` draggable="false" id="col1" > - First Column +
+ First Column +
@@ -57,57 +69,93 @@ exports[` custom column headers 1`] = ` class="grid-row-alternate" > @@ -142,7 +190,7 @@ exports[` custom header and info message 1`] = ` class="grid-messages" />
- Second Column +
+ Second Column +
- Third Column +
+ Third Column +
- abc +
+ abc +
- 123 +
+ 123 +
- 2019-01-01 +
+ 2019-01-01 +
- def +
+ def +
- 456 +
+ 456 +
- 2019-01-02 +
+ 2019-01-02 +
- ghi +
+ ghi +
- 789 +
+ 789 +
- 2019-01-03 +
+ 2019-01-03 +
@@ -151,21 +199,33 @@ exports[` custom header and info message 1`] = ` draggable="false" id="col1" > - col1 +
+ col1 +
@@ -174,57 +234,93 @@ exports[` custom header and info message 1`] = ` class="grid-row-alternate" > @@ -280,7 +376,7 @@ exports[` no data 1`] = ` class="grid-messages" />
- col2 +
+ col2 +
- col3 +
+ col3 +
- abc +
+ abc +
- 123 +
+ 123 +
- 2019-01-01 +
+ 2019-01-01 +
- def +
+ def +
- 456 +
+ 456 +
- 2019-01-02 +
+ 2019-01-02 +
- ghi +
+ ghi +
- 789 +
+ 789 +
- 2019-01-03 +
+ 2019-01-03 +
@@ -326,7 +422,7 @@ exports[` one row of data 1`] = ` class="grid-messages" />
@@ -335,7 +431,11 @@ exports[` one row of data 1`] = ` draggable="false" id="test" > - test +
+ test +
@@ -344,9 +444,13 @@ exports[` one row of data 1`] = ` class="grid-row-alternate" > @@ -386,7 +490,7 @@ exports[` previewData.warningMsg 1`] = ` class="grid-messages" />
- 123 +
+ 123 +
@@ -395,21 +499,33 @@ exports[` previewData.warningMsg 1`] = ` draggable="false" id="col1" > - col1 +
+ col1 +
@@ -418,57 +534,93 @@ exports[` previewData.warningMsg 1`] = ` class="grid-row-alternate" > @@ -502,7 +654,7 @@ exports[` three rows of data 1`] = ` class="grid-messages" />
- col2 +
+ col2 +
- col3 +
+ col3 +
- abc +
+ abc +
- 123 +
+ 123 +
- 2019-01-01 +
+ 2019-01-01 +
- def +
+ def +
- 456 +
+ 456 +
- 2019-01-02 +
+ 2019-01-02 +
- ghi +
+ ghi +
- 789 +
+ 789 +
- 2019-01-03 +
+ 2019-01-03 +
@@ -511,21 +663,33 @@ exports[` three rows of data 1`] = ` draggable="false" id="col1" > - col1 +
+ col1 +
@@ -534,57 +698,93 @@ exports[` three rows of data 1`] = ` class="grid-row-alternate" > @@ -624,7 +824,7 @@ exports[` warning message 1`] = ` class="grid-messages" />
- col2 +
+ col2 +
- col3 +
+ col3 +
- abc +
+ abc +
- 123 +
+ 123 +
- 2019-01-01 +
+ 2019-01-01 +
- def +
+ def +
- 456 +
+ 456 +
- 2019-01-02 +
+ 2019-01-02 +
- ghi +
+ ghi +
- 789 +
+ 789 +
- 2019-01-03 +
+ 2019-01-03 +
@@ -633,21 +833,33 @@ exports[` warning message 1`] = ` draggable="false" id="col1" > - col1 +
+ col1 +
@@ -656,57 +868,93 @@ exports[` warning message 1`] = ` class="grid-row-alternate" > @@ -752,7 +1000,7 @@ exports[` warning message and previewData.warningMsg 1`] = ` class="grid-messages" />
- col2 +
+ col2 +
- col3 +
+ col3 +
- abc +
+ abc +
- 123 +
+ 123 +
- 2019-01-01 +
+ 2019-01-01 +
- def +
+ def +
- 456 +
+ 456 +
- 2019-01-02 +
+ 2019-01-02 +
- ghi +
+ ghi +
- 789 +
+ 789 +
- 2019-01-03 +
+ 2019-01-03 +
@@ -761,21 +1009,33 @@ exports[` warning message and previewData.warningMsg 1`] = ` draggable="false" id="col1" > - col1 +
+ col1 +
@@ -784,57 +1044,93 @@ exports[` warning message and previewData.warningMsg 1`] = ` class="grid-row-alternate" > diff --git a/packages/components/src/internal/components/lineage/constants.tsx b/packages/components/src/internal/components/lineage/constants.tsx index 9d7f3280cb..7f9598d92d 100644 --- a/packages/components/src/internal/components/lineage/constants.tsx +++ b/packages/components/src/internal/components/lineage/constants.tsx @@ -40,7 +40,6 @@ export const LINEAGE_GRID_COLUMNS = List([ new GridColumn({ index: 'name', title: 'ID', - width: 270, cell: (name: string, node: Map) => { const indent = node.get('distance') * 10; const dupeCount = node.get('duplicateCount'); @@ -70,7 +69,6 @@ export const LINEAGE_GRID_COLUMNS = List([ new GridColumn({ index: 'distance', title: 'Distance', - width: 60, cell: (distance: any, node: Map) => { const gen = distance > 1 ? ' generations' : ' generation'; @@ -86,7 +84,6 @@ export const LINEAGE_GRID_COLUMNS = List([ new GridColumn({ index: 'lsid', title: 'Change Seed', - width: 70, cell: (lsid: string, node: Map) => { const lineageDistance = node.get('lineageDistance'); const baseURL = AppURL.create('lineage').addParams({ diff --git a/packages/components/src/internal/renderers.tsx b/packages/components/src/internal/renderers.tsx index 31ce9fbe74..091713a66c 100644 --- a/packages/components/src/internal/renderers.tsx +++ b/packages/components/src/internal/renderers.tsx @@ -203,15 +203,16 @@ const HeaderCellDropdownMenu: FC = memo(props => { let left; if (toggleEl.current && menuEl.current) { - const headerRect = toggleEl.current.parentElement.getBoundingClientRect(); + // The third parentElement is the ); } diff --git a/packages/components/src/internal/renderers/StorageStatusRenderer.tsx b/packages/components/src/internal/renderers/StorageStatusRenderer.tsx index 217ea3b903..a00348e28f 100644 --- a/packages/components/src/internal/renderers/StorageStatusRenderer.tsx +++ b/packages/components/src/internal/renderers/StorageStatusRenderer.tsx @@ -14,7 +14,7 @@ export class StorageStatusRenderer extends React.PureComponent{value}; + return value; } else { return {value}; } diff --git a/packages/components/src/internal/renderers/__snapshots__/DefaultRenderer.test.tsx.snap b/packages/components/src/internal/renderers/__snapshots__/DefaultRenderer.test.tsx.snap index 7dea3529a8..e8623305a9 100644 --- a/packages/components/src/internal/renderers/__snapshots__/DefaultRenderer.test.tsx.snap +++ b/packages/components/src/internal/renderers/__snapshots__/DefaultRenderer.test.tsx.snap @@ -2,31 +2,19 @@ exports[`DefaultRenderer boolean 1`] = `
- - true - + true
`; exports[`DefaultRenderer displayValue 1`] = `
- - Value 1 - + Value 1
`; exports[`DefaultRenderer formattedValue 1`] = `
- - Value 1.00 - + Value 1.00
`; @@ -46,37 +34,22 @@ exports[`DefaultRenderer list 1`] = ` exports[`DefaultRenderer new line 1`] = `
- - test1 + test1 test2 -
`; exports[`DefaultRenderer string 1`] = `
- - test string - + test string
`; -exports[`DefaultRenderer undefined 1`] = ` -
- -
-`; +exports[`DefaultRenderer undefined 1`] = `
`; exports[`DefaultRenderer url 1`] = `
Value 1 @@ -86,28 +59,20 @@ exports[`DefaultRenderer url 1`] = ` exports[`DefaultRenderer url, but noLink 1`] = `
- - Value 1 - + Value 1
`; exports[`DefaultRenderer value 1`] = `
- - 1 - + 1
`; exports[`DefaultRenderer with style, conditional formatting enabled 1`] = `
Value 1.00 @@ -117,10 +82,6 @@ exports[`DefaultRenderer with style, conditional formatting enabled 1`] = ` exports[`DefaultRenderer with style, conditional formatting not enabled 1`] = `
- - Value 1.00 - + Value 1.00
`; diff --git a/packages/components/src/public/QueryModel/GridPanel.tsx b/packages/components/src/public/QueryModel/GridPanel.tsx index 1586085ea5..b3c3ab5178 100644 --- a/packages/components/src/public/QueryModel/GridPanel.tsx +++ b/packages/components/src/public/QueryModel/GridPanel.tsx @@ -1057,8 +1057,6 @@ export class GridPanel extends PureComponent, State> { const { actions, allowSelections, - allowFiltering, - allowSorting, allowViewCustomization, hasHeader, asPanel, @@ -1176,7 +1174,6 @@ export class GridPanel extends PureComponent, State> { {hasData && ( .expired-grid-cell-content { padding: 5px; background-image: linear-gradient(225deg, red, red 5px, transparent 5px, transparent); + white-space: nowrap; } td > .expired-form-field { @@ -643,3 +645,30 @@ td > .expired-form-field { scroll-margin: 0; } } + +.text-left { + text-align: left; +} +.text-right { + text-align: right; +} +.text-center { + text-align: center; +} + +.read-only-table td, +.read-only-table th { + white-space: pre-wrap; // pre-wrap for multiline column cells + vertical-align: top; +} + +.read-only-table .table-cell-content { + // min-width: 100% is needed to ensure that table-cell-content will always fill the available space, otherwise it + // will only get as wide as the content, which negates the right-aligned style we give for numbers. + min-width: 100%; + max-width: 300px; + // width: max-content makes the table-cell-content elements grow as wide as their content will allow, up to 300px, + // which is the behavior we want, instead of the typical table layout algorithm. + width: max-content; + word-break: break-word; +} diff --git a/packages/components/src/theme/query-model.scss b/packages/components/src/theme/query-model.scss index 63e347dec3..88ce10f853 100644 --- a/packages/components/src/theme/query-model.scss +++ b/packages/components/src/theme/query-model.scss @@ -269,7 +269,7 @@ } .editable-grid__container.grid-panel__lock-left-with-countcol .table-responsive { thead th:nth-child(2), tr td:nth-child(2) { - left: 43px; + left: 35px; } }
- col2 +
+ col2 +
- col3 +
+ col3 +
- abc +
+ abc +
- 123 +
+ 123 +
- 2019-01-01 +
+ 2019-01-01 +
- def +
+ def +
- 456 +
+ 456 +
- 2019-01-02 +
+ 2019-01-02 +
- ghi +
+ ghi +
- 789 +
+ 789 +
- 2019-01-03 +
+ 2019-01-03 +
element, and we want to pin the menu to the bottom of that + const headerRect = toggleEl.current.parentElement.parentElement.parentElement.getBoundingClientRect(); const menuRect = menuEl.current.getBoundingClientRect(); - left = headerRect.x - menuRect.width + 18 + 'px'; - top = headerRect.y + headerRect.height + 5 + 'px'; + left = headerRect.right - menuRect.width + 'px'; + top = headerRect.bottom + 'px'; // Issue 45553 // Render the dropdown menu above the header if the header is too close to the bottom of the screen. if (headerRect.bottom + menuRect.height > window.innerHeight) { - top = headerRect.y - menuRect.height - 10 + 'px'; + top = headerRect.top - menuRect.height - 10 + 'px'; } } @@ -329,7 +330,7 @@ const HeaderCellDropdownMenu: FC = memo(props => { ); return ( -
+
{/* Note: we don't need a click handler on this icon because there is one on the wrapping div above */} {createPortal(body, portalRef)} @@ -401,7 +402,7 @@ export const HeaderCellDropdown: FC = memo(props => { return (
- +
= memo(props => { )} - +
{includeDropdown && !editingTitle && ( = memo(({ col, data, noLink }) => { let display = null; let style; - // Issue 43474: Prevent text wrapping for date columns - const noWrap = col?.jsonType === 'date' || col?.jsonType === 'time'; - // Issue 36941: when using the default renderer, add css so that line breaks as preserved - let className = noWrap ? 'ws-no-wrap' : 'ws-pre-wrap'; if (data) { if (typeof data === 'string') { @@ -55,15 +51,15 @@ export const DefaultRenderer: FC = memo(({ col, data, noLink }) => { display = data ? 'true' : 'false'; } else if (List.isList(data)) { // defensively return a MultiValueRenderer, this column likely wasn't declared properly as "multiValue" - return ; + return ; } else if (col?.isFileInput) { return ; - } - else { + } else { + let className: string; if (isConditionalFormattingEnabled()) { style = getDataStyling(data); if (style?.backgroundColor) { - className += ' status-pill'; + className = 'status-pill'; } } if (data.has('formattedValue')) { @@ -83,14 +79,18 @@ export const DefaultRenderer: FC = memo(({ col, data, noLink }) => { ); } + + if (style !== undefined) { + return ( + + {display} + + ); + } } } - return ( - - {display} - - ); + return display; }); DefaultRenderer.displayName = 'DefaultRenderer'; diff --git a/packages/components/src/internal/renderers/ExpirationDateColumnRenderer.tsx b/packages/components/src/internal/renderers/ExpirationDateColumnRenderer.tsx index 1db192fafa..fde74dfa92 100644 --- a/packages/components/src/internal/renderers/ExpirationDateColumnRenderer.tsx +++ b/packages/components/src/internal/renderers/ExpirationDateColumnRenderer.tsx @@ -5,11 +5,12 @@ import classNames from 'classnames'; import { QueryColumn } from '../../public/QueryColumn'; import { isDateTimeInPast } from '../util/Date'; +import { getTextAlignClassName } from '../components/base/models/GridColumn'; export interface ExpirationDateColumnRendererProps { col?: QueryColumn; columnIndex?: number; - data: Map | { [key: string]: any }; + data: Map | Record; tableCell?: boolean; } @@ -35,19 +36,10 @@ export const ExpirationDateColumnRenderer: FC if (tableCell) { return (
-
- {displayValue} -
+
{displayValue}