Skip to content

Commit

Permalink
Mesa fix layout (#1298)
Browse files Browse the repository at this point in the history
* Simplify table markup and remove unnecessary events and layout updates

* modifications needed for mesa table updates
  • Loading branch information
dmfalke authored Dec 9, 2024
1 parent a628d62 commit 467eb3b
Show file tree
Hide file tree
Showing 12 changed files with 109 additions and 204 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { debounce } from 'lodash';

import MesaTooltip from './MesaTooltip';
import Events from '../Utils/Events';
import { MESA_SCROLL_EVENT, MESA_REFLOW_EVENT } from '../Ui/MesaContants';

class AnchoredTooltip extends React.Component {
constructor(props) {
Expand All @@ -19,8 +18,6 @@ class AnchoredTooltip extends React.Component {
this.listeners = {
scroll: Events.add('scroll', this.updatePosition),
resize: Events.add('resize', this.updatePosition),
MesaScroll: Events.add(MESA_SCROLL_EVENT, this.updatePosition),
MesaReflow: Events.add(MESA_REFLOW_EVENT, this.updatePosition),
};
}

Expand Down
131 changes: 38 additions & 93 deletions packages/libs/coreui/src/components/Mesa/Ui/DataTable.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,19 @@ import { defaultMemoize } from 'reselect';
import HeadingRow from './HeadingRow';
import DataRowList from './DataRowList';
import { makeClassifier, combineWidths } from '../Utils/Utils';
import { MESA_SCROLL_EVENT, MESA_REFLOW_EVENT } from './MesaContants';

const dataTableClass = makeClassifier('DataTable');

class DataTable extends React.Component {
constructor(props) {
super(props);
this.widthCache = {};
this.state = { dynamicWidths: null, tableWrapperWidth: null };
this.widthCache = [];
this.renderStickyTable = this.renderStickyTable.bind(this);
this.componentDidMount = this.componentDidMount.bind(this);
this.getInnerCellWidth = this.getInnerCellWidth.bind(this);
this.hasSelectionColumn = this.hasSelectionColumn.bind(this);
this.hasExpansionColumn = this.hasExpansionColumn.bind(this);
this.shouldUseStickyHeader = this.shouldUseStickyHeader.bind(this);
this.makeFirstNColumnsSticky = this.makeFirstNColumnsSticky.bind(this);
this.handleTableBodyScroll = this.handleTableBodyScroll.bind(this);
this.setDynamicWidths = this.setDynamicWidths.bind(this);
this.resizeId = -1;
this.mainRef = null;
Expand All @@ -40,7 +37,7 @@ class DataTable extends React.Component {
}

makeFirstNColumnsSticky(columns, n) {
const { dynamicWidths } = this.state;
const dynamicWidths = this.widthCache;

if (n <= columns.length) {
const stickyColumns = columns.slice(0, n).map((column, index) => {
Expand Down Expand Up @@ -95,14 +92,16 @@ class DataTable extends React.Component {
}

attachLoadEventHandlers() {
if (this.bodyNode == null) return;
this.bodyNode.querySelectorAll('img, iframe, object').forEach((node) => {
if (node.complete) return;
node.addEventListener('load', (event) => {
const el = event.target.offsetParent || event.target;
if (el.scrollWidth > el.clientWidth) this.setDynamicWidths();
if (this.contentTable == null) return;
this.contentTable
.querySelectorAll('img, iframe, object')
.forEach((node) => {
if (node.complete) return;
node.addEventListener('load', (event) => {
const el = event.target.offsetParent || event.target;
if (el.scrollWidth > el.clientWidth) this.setDynamicWidths();
});
});
});
}

attachResizeHandler() {
Expand All @@ -123,11 +122,9 @@ class DataTable extends React.Component {
if (this.props.rows.length === 0 || this.props.filteredRows.length === 0)
return;

this.setState({ dynamicWidths: null, tableWrapperWidth: null }, () => {
this.widthCache = {};
const { columns } = this.props;
const hasSelectionColumn = this.hasSelectionColumn();
const { contentTable, getInnerCellWidth } = this;
this.setState({ dynamicWidths: null }, () => {
this.widthCache = [];
const { contentTable } = this;
if (!contentTable) return;
const contentCells = Array.from(
contentTable.querySelectorAll('tbody > tr:first-child > td')
Expand All @@ -137,26 +134,18 @@ class DataTable extends React.Component {
return;
}

if (hasSelectionColumn) {
contentCells.shift();
}

const dynamicWidths = columns.map(
(c, i) =>
getInnerCellWidth(contentCells[i], c) -
(hasSelectionColumn && !i ? 1 : 0)
this.widthCache = contentCells.map(
(cell) => cell.getBoundingClientRect().width
);
this.setState({ dynamicWidths }, () => {
window.dispatchEvent(new CustomEvent(MESA_REFLOW_EVENT));
const tableWrapperWidth = this.bodyNode && this.bodyNode.clientWidth;
this.setState({ tableWrapperWidth });
});
});
}

getInnerCellWidth(cell, { key }) {
if (key && key in this.widthCache) return this.widthCache[key];
return (this.widthCache[key] = cell.clientWidth);
hasExpansionColumn() {
const { options, eventHandlers } = this.props;
return (
typeof options.childRow === 'function' &&
typeof eventHandlers.onExpandedRowsChange === 'function'
);
}

hasSelectionColumn() {
Expand All @@ -168,12 +157,6 @@ class DataTable extends React.Component {
);
}

handleTableBodyScroll() {
const offset = this.bodyNode.scrollLeft;
this.headerNode.scrollLeft = offset;
window.dispatchEvent(new CustomEvent(MESA_SCROLL_EVENT));
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

renderStickyTable() {
Expand All @@ -187,30 +170,15 @@ class DataTable extends React.Component {
uiState,
headerWrapperStyle,
} = this.props;
const { dynamicWidths } = this.state;
const stickyColumns = options.useStickyFirstNColumns
const newColumns = options.useStickyFirstNColumns
? this.makeFirstNColumnsSticky(columns, options.useStickyFirstNColumns)
: columns;
const newColumns =
stickyColumns.every(({ width }) => width) ||
!dynamicWidths ||
dynamicWidths.length == 0
? stickyColumns
: makeColumnsWithDynamicWidths({
columns: stickyColumns,
dynamicWidths,
});
const wrapperStyle = {
maxHeight: options ? options.tableBodyMaxHeight : null,
minWidth: dynamicWidths
? combineWidths(columns.map(({ width }) => width))
: null,
};
const headerWrapperStyleMerged = {
display: dynamicWidths == null ? 'none' : 'block',
...headerWrapperStyle,
const tableStyle = {
tableLayout: 'auto',
};
const tableLayout = { tableLayout: dynamicWidths ? 'fixed' : 'auto' };
const tableProps = {
options,
rows,
Expand All @@ -223,36 +191,21 @@ class DataTable extends React.Component {
return (
<div ref={(node) => (this.mainRef = node)} className="MesaComponent">
<div
className={dataTableClass(
null,
options.useStickyHeader ? 'Sticky' : null
)}
className={dataTableClass(null, [
options.useStickyHeader ? 'Sticky' : undefined,
options.marginContent ? 'HasMargin' : undefined,
])}
style={wrapperStyle}
>
<div
style={headerWrapperStyleMerged}
ref={(node) => (this.headerNode = node)}
className={dataTableClass('Header')}
>
<table cellSpacing={0} cellPadding={0} style={{ ...tableLayout }}>
<HeadingRow {...tableProps} />
</table>
</div>
<div
ref={(node) => (this.bodyNode = node)}
className={dataTableClass('Body')}
onScroll={this.handleTableBodyScroll}
<table
cellSpacing={0}
cellPadding={0}
style={tableStyle}
ref={(node) => (this.contentTable = node)}
>
<table
cellSpacing={0}
cellPadding={0}
style={tableLayout}
ref={(node) => (this.contentTable = node)}
>
{dynamicWidths == null ? <HeadingRow {...tableProps} /> : null}
<DataRowList {...tableProps} />
</table>
</div>
<HeadingRow {...tableProps} />
<DataRowList {...tableProps} />
</table>
{this.props.options.marginContent && (
<div className={dataTableClass('Margin')}>
{this.props.options.marginContent}
Expand Down Expand Up @@ -289,12 +242,4 @@ DataTable.propTypes = {
eventHandlers: PropTypes.objectOf(PropTypes.func),
};

const makeColumnsWithDynamicWidths = defaultMemoize(
({ columns, dynamicWidths }) =>
columns.map((column, index) =>
Object.assign({}, column, { width: dynamicWidths[index] })
),
(a, b) => a.columns === b.columns && isEqual(a.dynamicWidths, b.dynamicWidths)
);

export default DataTable;
20 changes: 6 additions & 14 deletions packages/libs/coreui/src/components/Mesa/Ui/ExpansionCell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,21 +42,13 @@ export default function ExpansionCell({
const title = 'Show or hide all row details';

return (
<th className="wdk-DataTableCell wdk-DataTableCell__childRowToggle">
<th className="HeadingCell ChildRowToggle">
{inert ? null : areAllRowsExpanded ? (
<button
className="wdk-DataTableCellExpand"
title={title}
onClick={handler}
>
<button title={title} onClick={handler}>
<ArrowDown />
</button>
) : (
<button
className="wdk-DataTableCellExpand"
title={title}
onClick={handler}
>
<button title={title} onClick={handler}>
<ArrowRight />
</button>
)}
Expand All @@ -82,13 +74,13 @@ export default function ExpansionCell({
};

return (
<td className="wdk-DataTable wdk-DataTableCell__childRowToggle">
<td className="ChildRowToggle">
{inert ? null : isExpanded ? (
<button className="wdk-DataTableCellExpand" onClick={handler}>
<button onClick={handler}>
<ArrowDown />
</button>
) : (
<button className="wdk-DataTableCellExpand" onClick={handler}>
<button onClick={handler}>
<ArrowRight />
</button>
)}
Expand Down
3 changes: 0 additions & 3 deletions packages/libs/coreui/src/components/Mesa/Ui/HeadingCell.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import Icon from '../Components/Icon';
import HelpTrigger from '../Components/HelpTrigger';
import { makeClassifier } from '../Utils/Utils';
import Events, { EventsFactory } from '../Utils/Events';
import { MESA_SCROLL_EVENT, MESA_REFLOW_EVENT } from './MesaContants';

const headingCellClass = makeClassifier('HeadingCell');

Expand Down Expand Up @@ -42,8 +41,6 @@ class HeadingCell extends React.PureComponent {
this.listeners = {
scroll: Events.add('scroll', this.updateOffset),
resize: Events.add('resize', this.updateOffset),
MesaScroll: Events.add(MESA_SCROLL_EVENT, this.updateOffset),
MesaReflow: Events.add(MESA_REFLOW_EVENT, this.updateOffset),
};
}

Expand Down
3 changes: 3 additions & 0 deletions packages/libs/coreui/src/components/Mesa/style/Cells.scss
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
$StickyColumnBorderColor: rgb(204, 204, 204);

.MesaComponent {
tr {
white-space: break-spaces;
}
th {
background-color: #e2e2e2;
transition: background 0.25s;
Expand Down
Loading

0 comments on commit 467eb3b

Please sign in to comment.