Skip to content
Merged
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.33-beta.4",
"version": "5.0.34-beta.0",
"description": "ui reactjs components for openstack marketing site",
"main": "lib/openstack-uicore-foundation.js",
"scripts": {
Expand Down
51 changes: 51 additions & 0 deletions src/components/mui/__tests__/mui-table.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,57 @@ describe("MuiTable", () => {
expect(onPerPageChange).toHaveBeenCalledWith(20);
});

describe("disableProp", () => {
const disabledData = [
{ id: 1, name: "Alice", role: "Dev", is_disabled: true },
{ id: 2, name: "Bob", role: "PM", is_disabled: false }
];
const disabledOptions = { sortCol: "", sortDir: 1, disableProp: "is_disabled" };

test("disables edit button for rows where disableProp is truthy", () => {
setup({ data: disabledData, onEdit: jest.fn(), options: disabledOptions });
const buttons = screen.getAllByTestId("action-edit");
expect(buttons[0]).toBeDisabled();
expect(buttons[1]).not.toBeDisabled();
});

test("disables delete button for rows where disableProp is truthy", () => {
setup({ data: disabledData, onDelete: jest.fn(), options: disabledOptions });
const buttons = screen.getAllByTestId("action-delete");
expect(buttons[0]).toBeDisabled();
expect(buttons[1]).not.toBeDisabled();
});

test("disables select button for rows where disableProp is truthy", () => {
setup({ data: disabledData, onSelect: jest.fn(), options: disabledOptions });
const buttons = screen.getAllByTestId("action-select");
expect(buttons[0]).toBeDisabled();
expect(buttons[1]).not.toBeDisabled();
});

test("disables archive button for rows where disableProp is truthy and not 'is_archived'", () => {
setup({ data: disabledData, onArchive: jest.fn(), options: disabledOptions });
const buttons = screen.getAllByTestId("action-archive");
expect(buttons[0]).toBeDisabled();
expect(buttons[1]).not.toBeDisabled();
});

test("does not disable archive button when disableProp is 'is_archived'", () => {
const archivedData = [
{ id: 1, name: "Alice", role: "Dev", is_archived: true },
{ id: 2, name: "Bob", role: "PM", is_archived: false }
];
setup({
data: archivedData,
onArchive: jest.fn(),
options: { sortCol: "", sortDir: 1, disableProp: "is_archived" }
});
const buttons = screen.getAllByTestId("action-archive");
expect(buttons[0]).not.toBeDisabled();
expect(buttons[1]).not.toBeDisabled();
});
});

test("renders boolean true as CheckIcon", () => {
const boolCols = [{ columnKey: "active", header: "Active" }];
render(
Expand Down
82 changes: 49 additions & 33 deletions src/components/mui/table/mui-table.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,10 @@ const ARCHIVED_CELL_SX = {
const ACTION_CELL_SX = {
p: 0,
textAlign: "center",
verticalAlign: "middle"
verticalAlign: "middle",
width: 40,
minWidth: 40,
maxWidth: 40
};

const MuiTable = ({
Expand Down Expand Up @@ -102,12 +105,32 @@ const MuiTable = ({

const {sortCol, sortDir} = options;

const getArchivedCellSx = (row) =>
options.disableProp && row[options.disableProp] ? ARCHIVED_CELL_SX : null;
const getDisabledSx = (row) =>
options.disableProp && row[options.disableProp] ? ARCHIVED_CELL_SX : {};

const getCellSx = (row, baseSx = {}) => ({
...baseSx,
...(getArchivedCellSx(row) || {})
const getHeaderSx = (col) => ({
...(col.width && {
width: col.width,
minWidth: col.width,
maxWidth: col.width
}),
...(col.headSx || {}),
})

const getCellSx = (row, col) => ({
fontWeight: "normal",
...(col.width && {
width: col.width,
minWidth: col.width,
maxWidth: col.width
}),
...(col.cellSx || {}),
...getDisabledSx(row)
});

const getActionCellSx = (row) => ({
...ACTION_CELL_SX,
...getDisabledSx(row)
});

const handleDelete = async (item) => {
Expand Down Expand Up @@ -143,7 +166,7 @@ const MuiTable = ({
);
}

return <span style={{ fontWeight: "normal" }}>{row[col.columnKey]}</span>;
return <span style={{fontWeight: "normal"}}>{row[col.columnKey]}</span>;
};

return (
Expand All @@ -160,11 +183,7 @@ const MuiTable = ({
{columns.map((col) => (
<TableCell
key={col.columnKey}
sx={{
width: col.width,
minWidth: col.width,
maxWidth: col.width
}}
sx={getHeaderSx(col)}
align={col.align ?? "left"}
>
{col.sortable ? (
Expand All @@ -191,10 +210,10 @@ const MuiTable = ({
)}
</TableCell>
))}
{onEdit && <TableCell sx={{...ACTION_CELL_SX, width: 40, minWidth: 40, maxWidth: 40}}/>}
{onEdit && <TableCell sx={ACTION_CELL_SX}/>}
{onArchive && <TableCell sx={{...ACTION_CELL_SX, width: 80, minWidth: 80, maxWidth: 80}}/>}
{onDelete && <TableCell sx={{...ACTION_CELL_SX, width: 40, minWidth: 40, maxWidth: 40}}/>}
{onSelect && <TableCell sx={{...ACTION_CELL_SX, width: 40, minWidth: 40, maxWidth: 40}}/>}
{onDelete && <TableCell sx={ACTION_CELL_SX}/>}
{onSelect && <TableCell sx={ACTION_CELL_SX}/>}
</TableRow>
</TableHead>

Expand All @@ -207,15 +226,8 @@ const MuiTable = ({
<TableCell
key={col.columnKey}
align={col.align ?? "left"}
className={`${
col.dottedBorder && styles.dottedBorderLeft
} ${col.className}`}
sx={getCellSx(row, {
width: col.width,
minWidth: col.width,
maxWidth: col.width,
fontWeight: "normal"
})}
className={`${col.dottedBorder && styles.dottedBorderLeft} ${col.className}`}
sx={getCellSx(row, col)}
>
{renderCell(row, col)}
</TableCell>
Expand All @@ -225,23 +237,23 @@ const MuiTable = ({
<TableCell
align="center"
className={styles.dottedBorderLeft}
sx={getCellSx(row, {...ACTION_CELL_SX, width: 40, minWidth: 40, maxWidth: 40})}
sx={getActionCellSx(row)}
>
<IconButton
size="medium"
onClick={() => onEdit(row)}
sx={{ padding: 0 }}
sx={{padding: 0}}
data-testid="action-edit"
disabled={options.disableProp && row[options.disableProp]}
>
<EditIcon fontSize="large" />
<EditIcon fontSize="large"/>
</IconButton>
</TableCell>
)}
{/* Archive column */}
{onArchive && (
<TableCell
align="center"
sx={getCellSx(row, {...ACTION_CELL_SX, width: 80, minWidth: 80, maxWidth: 80})}
sx={{...getActionCellSx(row), width: 80, minWidth: 80, maxWidth: 80}}
className={styles.dottedBorderLeft}
>
<Button
Expand All @@ -258,6 +270,8 @@ const MuiTable = ({
padding: 0,
color: "rgba(0,0,0,0.56)"
}}
// bypass disabled if disableProp is "is_archived"
disabled={options.disableProp && options.disableProp !== "is_archived" && row[options.disableProp]}
>
{row.is_archived
? T.translate("general.unarchive")
Expand All @@ -270,14 +284,15 @@ const MuiTable = ({
<TableCell
align="center"
className={styles.dottedBorderLeft}
sx={getCellSx(row, {...ACTION_CELL_SX, width: 40, minWidth: 40, maxWidth: 40})}
sx={getActionCellSx(row)}
>
{canDelete(row) && (
<IconButton
size="medium"
onClick={() => handleDelete(row)}
data-testid="action-delete"
sx={{ padding: 0 }}
sx={{padding: 0}}
disabled={options.disableProp && row[options.disableProp]}
>
<DeleteIcon fontSize="large"/>
</IconButton>
Expand All @@ -287,14 +302,15 @@ const MuiTable = ({
{onSelect && (
<TableCell
align="center"
sx={getCellSx(row, {...ACTION_CELL_SX, width: 40, minWidth: 40, maxWidth: 40})}
sx={getActionCellSx(row)}
className={styles.dottedBorderLeft}
>
<IconButton
size="medium"
onClick={() => onSelect(row)}
data-testid="action-select"
sx={{ padding: 0 }}
sx={{padding: 0}}
disabled={options.disableProp && row[options.disableProp]}
>
<ArrowForwardIcon/>
</IconButton>
Expand Down
Loading