@o2xp/react-datatable
Version:
@o2xp/react-datatable is a modulable component to render data in a table with some nice features !
225 lines (211 loc) • 6.4 kB
JavaScript
import React, { Component, Fragment } from "react";
import { connect } from "react-redux";
import copy from "copy-to-clipboard";
import {
rowPropType,
columnsPropType,
columnsOrderPropType,
CustomTableBodyCellPropType,
columnSizeMultiplierPropType,
keyColumnPropType,
editingPropType,
rowsSelectedPropType,
stylePropType,
copyToClipboardPropType,
enqueueSnackbarPropType,
customPropsPropType
} from "../../../proptypes";
import BodyCell from "./BodyCell";
import BodyActionsCell from "./BodyActionsCell";
import { enqueueSnackbar as enqueueSnackbarAction } from "../../../redux/actions/notifierActions";
export class BodyRow extends Component {
copyToClipboardFunction = val => {
const { enqueueSnackbar, copyToClipboard } = this.props;
if (copyToClipboard) {
copy(val);
enqueueSnackbar({
message: "Cell's content has been copied to clipboard.",
options: {
key: new Date().getTime() + Math.random(),
variant: "info"
}
});
}
};
bodyCellBuilder = (val, columnId, cellIndex, row, editing) => {
const {
columns,
columnsOrder,
CustomTableBodyCell,
columnSizeMultiplier,
rowsSelected,
keyColumn,
style,
customProps
} = this.props;
const columnOrderIndex = columnsOrder.findIndex(col => col === columnId);
const column = columns.find(col => col.id === columnId);
let indexLastLocked = columns.filter(col => col.locked).length - 1;
if (columnsOrder.find(col => col === "o2xpActions")) {
indexLastLocked += 1;
}
const isLastLocked = indexLastLocked === columnOrderIndex;
const rowId = row[keyColumn];
const key = `row-${row[keyColumn]}-cell-${columnId}`;
let isEditing = editing && column.editable;
if (row.editableId && !row.editableId.includes(columnId)) {
isEditing = false;
}
if (columnId === "o2xpActions") {
const checked = !!rowsSelected.find(r => r[keyColumn] === row[keyColumn]);
return (
<BodyActionsCell
style={style}
isLastLocked={isLastLocked}
key={key}
column={column}
row={row}
editing={editing}
checked={checked}
/>
);
}
const width = `${(
(Number(column.colSize.split("px")[0]) + 35) *
columnSizeMultiplier
).toString()}px`;
if (column.locked) {
let totalLeft = 0;
for (let i = 0; i <= columnOrderIndex - 1; i += 1) {
totalLeft +=
Number(
columns
.find(col => col.id === columnsOrder[i])
.colSize.split("px")[0]
) + 50;
}
const left = `${totalLeft.toString()}px`;
return (
<BodyCell
isLastLocked={isLastLocked}
cellVal={val}
editing={isEditing}
width={column.colSize}
column={column}
rowId={rowId}
key={key}
style={{
position: "sticky",
left,
zIndex: 9,
backgroundColor: style.backgroundColor
}}
onClick={() => (isEditing ? null : this.copyToClipboardFunction(val))}
/>
);
}
if ((val === null || val === undefined || val === "") && !isEditing) {
return (
<div className="Table-Cell" key={key}>
<div style={{ width }}>
<div className="no-data" />
</div>
</div>
);
}
if (CustomTableBodyCell !== null && !isEditing) {
return (
<div className="Table-Cell" key={key}>
<div style={{ width }}>
<CustomTableBodyCell
customProps={customProps}
cellVal={val}
column={column}
rowId={rowId}
onClick={() => this.copyToClipboardFunction(val)}
/>
</div>
</div>
);
}
return (
<BodyCell
cellVal={val}
editing={isEditing}
width={width}
column={column}
rowId={rowId}
key={key}
onClick={() => (isEditing ? null : this.copyToClipboardFunction(val))}
/>
);
};
render() {
const { style, row, columnsOrder, editing, keyColumn } = this.props;
return (
<Fragment>
<div
style={{
top: style.top,
height: style.height,
position: style.position
}}
>
<div
className={`Table-Row Table-Row-${row[keyColumn]}`}
style={{
height: style.height,
backgroundColor: style.backgroundColor
}}
>
{columnsOrder.map((columnId, cellIndex) => {
return this.bodyCellBuilder(
row[columnId],
columnId,
cellIndex,
row,
editing
);
})}
</div>
</div>
</Fragment>
);
}
}
BodyRow.propTypes = {
row: rowPropType.isRequired,
customProps: customPropsPropType,
columnsOrder: columnsOrderPropType.isRequired,
columns: columnsPropType.isRequired,
columnSizeMultiplier: columnSizeMultiplierPropType.isRequired,
style: stylePropType.isRequired,
keyColumn: keyColumnPropType.isRequired,
editing: editingPropType.isRequired,
enqueueSnackbar: enqueueSnackbarPropType,
rowsSelected: rowsSelectedPropType.isRequired,
copyToClipboard: copyToClipboardPropType.isRequired,
CustomTableBodyCell: CustomTableBodyCellPropType
};
const mapDispatchToProps = dispatch => {
return {
enqueueSnackbar: ({ message, options }) =>
dispatch(enqueueSnackbarAction({ message, options }))
};
};
const mapStateToProps = state => {
return {
customProps: state.customComponentsReducer.customProps,
columns: state.datatableReducer.data.columns,
copyToClipboard:
state.datatableReducer.features.userConfiguration.copyToClipboard,
keyColumn: state.datatableReducer.keyColumn,
rowsSelected: state.datatableReducer.rowsSelected,
columnsOrder:
state.datatableReducer.features.userConfiguration.columnsOrder,
columnSizeMultiplier:
state.datatableReducer.dimensions.columnSizeMultiplier,
CustomTableBodyCell: state.customComponentsReducer.CustomTableBodyCell
};
};
export default connect(mapStateToProps, mapDispatchToProps)(BodyRow);