Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "openstack-uicore-foundation",
"version": "5.0.60",
"version": "5.0.61-beta.7",
"description": "ui reactjs components for openstack marketing site",
"main": "lib/openstack-uicore-foundation.js",
"scripts": {
Expand Down
71 changes: 52 additions & 19 deletions src/components/mui/BulkEditTable/BulkEditTable.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,12 @@ import Row from "./components/Row";
import useRowSelection from "./hooks/useRowSelection";
import styles from "./BulkEditTable.module.less";
import CustomTablePagination from "../tables/components/CustomTablePagination";
import parsePaginationPosition from "../tables/components/pagination-position";
import showConfirmDialog from "../showConfirmDialog";
import {
RESPONSIVE_TABLE_SX,
getActionsMenuBreakpoint
} from "../tables/components/table-styles";

const BulkEditTable = ({
options,
Expand All @@ -42,6 +47,8 @@ const BulkEditTable = ({
currentPage,
onPageChange,
onPerPageChange,
paginationPosition,
pageSliderVisible,
idKey,
onEdit,
onDelete,
Expand All @@ -64,6 +71,9 @@ const BulkEditTable = ({
reset
} = useRowSelection(idKey);

const collapseActions = (onEdit ? 1 : 0) + (onDelete ? 1 : 0) >= 2;
const actionsBreakpoint = getActionsMenuBreakpoint(columns.length);

const dataIds = data.map((row) => row[idKey]).join(",");

// reset selection/edit state whenever the set of rows shown changes
Expand Down Expand Up @@ -108,22 +118,50 @@ const BulkEditTable = ({
}
};

const showPagination = !!(perPage && currentPage && onPageChange);
const { showTop, showBottom } = parsePaginationPosition(paginationPosition);
const renderPagination = (showRange) => (
<CustomTablePagination
totalRows={totalRows}
perPage={perPage}
currentPage={currentPage}
onPageChange={onPageChange}
onPerPageChange={onPerPageChange}
showRange={showRange}
pageSliderVisible={pageSliderVisible}
/>
);

return (
<Box sx={{ width: "100%" }}>
<Toolbar
editEnabled={editEnabled}
hasSelection={selectedRows.length > 0}
onEdit={enterEditMode}
onApply={handleUpdateEvents}
onCancel={cancel}
/>
<Box
sx={{
display: "flex",
alignItems: "center",
justifyContent: "space-between",
flexWrap: "wrap",
gap: 1.5,
mb: 2
}}
>
<Toolbar
editEnabled={editEnabled}
selectedCount={selectedRows.length}
onEdit={enterEditMode}
onApply={handleUpdateEvents}
onCancel={cancel}
/>
{showPagination && showTop && (
<Box sx={{ display: { xs: "none", sm: "block" } }}>{renderPagination(false)}</Box>
)}
</Box>
<Paper elevation={0} sx={{ width: "100%", mb: 2 }}>
<TableContainer
component={Paper}
className={styles.tableWrapper}
sx={{ borderRadius: 0, boxShadow: "none" }}
>
<Table>
<Table sx={RESPONSIVE_TABLE_SX}>
<TableHead sx={{ backgroundColor: "#EAEDF4" }}>
<TableRow>
<TableCell
Expand All @@ -142,7 +180,6 @@ const BulkEditTable = ({
</TableCell>
{columns.map((col, i) => {
const sortable = !!col.sortable;
const colWidth = col.width ?? "";

return (
<Heading
Expand All @@ -152,7 +189,7 @@ const BulkEditTable = ({
sortable={sortable}
columnIndex={i}
columnKey={col.columnKey}
width={colWidth}
col={col}
key={`heading_${col.columnKey}`}
>
{col.header ?? col.label ?? col.value}
Expand Down Expand Up @@ -187,20 +224,14 @@ const BulkEditTable = ({
columns={columns}
onEdit={onEdit}
onDelete={onDelete ? handleDelete : null}
collapseActions={collapseActions}
actionsBreakpoint={actionsBreakpoint}
/>
))}
</TableBody>
</Table>
</TableContainer>
{perPage && currentPage && onPageChange && (
<CustomTablePagination
totalRows={totalRows}
perPage={perPage}
currentPage={currentPage}
onPageChange={onPageChange}
onPerPageChange={onPerPageChange}
/>
)}
{showPagination && showBottom && renderPagination(true)}
</Paper>
</Box>
);
Expand All @@ -218,6 +249,8 @@ BulkEditTable.propTypes = {
currentPage: PropTypes.number,
onPageChange: PropTypes.func,
onPerPageChange: PropTypes.func,
paginationPosition: PropTypes.string,
pageSliderVisible: PropTypes.bool,
onEdit: PropTypes.func,
onDelete: PropTypes.func,
getName: PropTypes.func,
Expand Down
6 changes: 0 additions & 6 deletions src/components/mui/BulkEditTable/BulkEditTable.module.less
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,8 @@
position: relative;

td {
max-width: 150px;
text-overflow: ellipsis;
overflow-wrap: break-word;
vertical-align: middle;

&.dataColumn {
min-width: 150px;
}
}

// shared by header (th) and body (td) cells so the checkbox/action columns
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ describe("BulkEditTable", () => {
const checkboxes = screen.getAllByRole("checkbox");

await user.click(checkboxes[1]);
await user.click(screen.getByText("bulk_edit_table.edit_selected"));
await user.click(screen.getByText(/^bulk_edit_table\.edit_selected/));
await act(async () => {
await user.click(screen.getByText("bulk_edit_table.apply_changes"));
});
Expand Down Expand Up @@ -86,7 +86,7 @@ describe("BulkEditTable", () => {

// select row 1 and enter edit mode
await user.click(checkboxes[1]);
await user.click(screen.getByText("bulk_edit_table.edit_selected"));
await user.click(screen.getByText(/^bulk_edit_table\.edit_selected/));

// type an edit into row 1's editable title cell
fireEvent.change(screen.getByRole("textbox"), {
Expand Down
7 changes: 4 additions & 3 deletions src/components/mui/BulkEditTable/components/Heading.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import Box from "@mui/material/Box";
import TableCell from "@mui/material/TableCell";
import TableSortLabel from "@mui/material/TableSortLabel";
import { visuallyHidden } from "@mui/utils";
import { getColumnWidthSx } from "../../tables/components/table-styles";

const Heading = (props) => {
const {
Expand All @@ -27,7 +28,7 @@ const Heading = (props) => {
onSort,
columnIndex,
columnKey,
width,
col,
children
} = props;

Expand All @@ -37,7 +38,7 @@ const Heading = (props) => {
onSort(columnIndex, columnKey, sortDir ? sortDir * -1 : 1);
};

const headerSx = width ? { width, minWidth: width, maxWidth: width } : {};
const headerSx = getColumnWidthSx(col);

if (!sortable || editEnabled) {
return <TableCell sx={headerSx}>{children}</TableCell>;
Expand Down Expand Up @@ -70,7 +71,7 @@ Heading.propTypes = {
columnIndex: PropTypes.number,
columnKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
sortable: PropTypes.bool,
width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
col: PropTypes.object.isRequired,
children: PropTypes.node
};

Expand Down
59 changes: 43 additions & 16 deletions src/components/mui/BulkEditTable/components/Row.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,17 @@ import Checkbox from "@mui/material/Checkbox";
import IconButton from "@mui/material/IconButton";
import EditIcon from "@mui/icons-material/Edit";
import DeleteIcon from "@mui/icons-material/Delete";
import T from "i18n-react/dist/i18n-react";
import Cell from "./Cell";
import RowActionsMenu from "../../tables/components/row-actions-menu";
import { getColumnWidthSx } from "../../tables/components/table-styles";
import styles from "../BulkEditTable.module.less";

// the 250px min-width while editing comes from the .bulkEditCol class
// (applied via className below) so it isn't duplicated here
const getCellStyle = (col) => ({
...(col.width
? { width: col.width, minWidth: col.width, maxWidth: col.width }
: {}),
// (applied via className below), so it overrides the adaptive width here
const getCellSx = (col, isEditingRow) => ({
...getColumnWidthSx(col),
...(isEditingRow && col.editableField ? { minWidth: 250 } : {}),
...col.customStyle
});

Expand All @@ -43,11 +45,24 @@ const Row = (props) => {
onFieldChange,
onEdit,
onDelete,
idKey
idKey,
collapseActions,
actionsBreakpoint
} = props;

const isEditingRow = isSelected && editEnabled;

const rowActions = [
onEdit && {
label: T.translate("general.edit"),
onClick: () => onEdit(row)
},
onDelete && {
label: T.translate("general.delete"),
onClick: () => onDelete(row)
}
].filter(Boolean);

const onRowChange = (ev) => {
const { value, id } = ev.target;
onFieldChange(id, value);
Expand All @@ -72,13 +87,8 @@ const Row = (props) => {
{columns.map((col) => (
<TableCell
key={`${row[idKey]}_${col.columnKey}`}
className={
isEditingRow && col.editableField
? styles.bulkEditCol
: styles.dataColumn
}
sx={{ fontWeight: "normal" }}
style={getCellStyle(col)}
className={isEditingRow && col.editableField ? styles.bulkEditCol : ""}
sx={{ fontWeight: "normal", ...getCellSx(col, isEditingRow) }}
>
<Cell
col={col}
Expand All @@ -95,7 +105,15 @@ const Row = (props) => {
className={`${styles.actionColumn} ${styles.dottedBorderLeft}`}
sx={{ backgroundColor: "#fff" }}
>
<Box sx={{ display: "flex", justifyContent: "center", gap: 1 }}>
<Box
sx={{
display: collapseActions
? { xs: "none", [actionsBreakpoint]: "flex" }
: "flex",
justifyContent: "center",
gap: 1
}}
>
{onEdit && (
<IconButton
size="medium"
Expand All @@ -117,6 +135,11 @@ const Row = (props) => {
</IconButton>
)}
</Box>
{collapseActions && (
<Box sx={{ display: { xs: "flex", [actionsBreakpoint]: "none" }, justifyContent: "center" }}>
<RowActionsMenu actions={rowActions} />
</Box>
)}
</TableCell>
)}
</TableRow>
Expand All @@ -133,13 +156,17 @@ Row.propTypes = {
onFieldChange: PropTypes.func,
onEdit: PropTypes.func,
onDelete: PropTypes.func,
idKey: PropTypes.string
idKey: PropTypes.string,
collapseActions: PropTypes.bool,
actionsBreakpoint: PropTypes.string
};

Row.defaultProps = {
idKey: "id",
onEdit: null,
onDelete: null
onDelete: null,
collapseActions: false,
actionsBreakpoint: "md"
};

export default Row;
30 changes: 24 additions & 6 deletions src/components/mui/BulkEditTable/components/Toolbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,31 +17,49 @@ import T from "i18n-react/dist/i18n-react";
import Box from "@mui/material/Box";
import Button from "@mui/material/Button";

const Toolbar = ({ editEnabled, hasSelection, onEdit, onApply, onCancel }) => (
<Box sx={{ display: "flex", gap: 1, mb: 2 }}>
const Toolbar = ({ editEnabled, selectedCount, onEdit, onApply, onCancel }) => (
<Box sx={{ display: "flex", gap: 1, width: { xs: "100%", sm: "auto" } }}>
{editEnabled ? (
<>
<Button variant="contained" onClick={onApply}>
<Button
variant="contained"
onClick={onApply}
sx={{ flex: { xs: 1, sm: "0 0 auto" } }}
>
{T.translate("bulk_edit_table.apply_changes")}
</Button>
<Button variant="outlined" onClick={onCancel}>
<Button
variant="outlined"
onClick={onCancel}
sx={{ flex: { xs: 1, sm: "0 0 auto" } }}
>
{T.translate("general.cancel")}
</Button>
</>
) : (
<Button variant="contained" onClick={onEdit} disabled={!hasSelection}>
<Button
variant="contained"
onClick={onEdit}
disabled={selectedCount === 0}
sx={{ width: { xs: "100%", sm: "auto" } }}
>
{T.translate("bulk_edit_table.edit_selected")}
{selectedCount > 0 ? ` (${selectedCount})` : ""}
</Button>
)}
</Box>
);

Toolbar.propTypes = {
editEnabled: PropTypes.bool,
hasSelection: PropTypes.bool,
selectedCount: PropTypes.number,
onEdit: PropTypes.func,
onApply: PropTypes.func,
onCancel: PropTypes.func
};

Toolbar.defaultProps = {
selectedCount: 0
};

export default Toolbar;
Loading
Loading