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
45 changes: 23 additions & 22 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@
"whatwg-fetch": "^3.6.20"
},
"dependencies": {
"@patternfly/react-drag-drop": "^6.3.0",
"@patternfly/react-drag-drop": "^6.0.0",
"@patternfly/react-tokens": "^6.0.0",
"sharp": "^0.34.0"
}
Expand Down
1 change: 1 addition & 0 deletions packages/module/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"react-jss": "^10.10.0"
},
"peerDependencies": {
"@patternfly/react-drag-drop": "^6.0.0",
"react": "^17 || ^18 || ^19",
"react-dom": "^17 || ^18 || ^19"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,11 @@ Clicking the "Manage columns" button will open the column management modal. The
```js file="./ColumnManagementModalExample.tsx"

```

### With drag and drop reordering

When `enableDragDrop` is set to `true`, users can drag and drop columns to reorder them. The order changes are reflected both in the modal and in the table when applied. This is useful when column order matters for the user experience.

```js file="./ColumnManagementModalDragDropExample.tsx"

```
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import { FunctionComponent, useState } from 'react';
import { Button, ButtonVariant } from '@patternfly/react-core';
import { Table, Tbody, Td, Th, Tr, Thead } from '@patternfly/react-table';
import { ColumnsIcon } from '@patternfly/react-icons';
import ColumnManagementModal, {
ColumnManagementModalColumn
} from '@patternfly/react-component-groups/dist/dynamic/ColumnManagementModal';

const DEFAULT_COLUMNS: ColumnManagementModalColumn[] = [
{
title: 'ID',
key: 'id',
isShownByDefault: true,
isShown: true,
isUntoggleable: true
},
{
title: 'Publish date',
key: 'publishDate',
isShownByDefault: true,
isShown: true
},
{
title: 'Impact',
key: 'impact',
isShownByDefault: true,
isShown: true
},
{
title: 'Score',
key: 'score',
isShownByDefault: false,
isShown: false
},
{
title: 'CVSS Vector',
key: 'cvssVector',
isShownByDefault: false,
isShown: false
},
{
title: 'Severity',
key: 'severity',
isShownByDefault: true,
isShown: true
}
];

const ROWS = [
{
id: 'CVE-2024-1546',
publishDate: '20 Feb 2024',
impact: 'Important',
score: '7.5',
cvssVector: 'CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N',
severity: 'High'
},
{
id: 'CVE-2024-1547',
publishDate: '20 Feb 2024',
impact: 'Important',
score: '7.5',
cvssVector: 'CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N',
severity: 'High'
},
{
id: 'CVE-2024-1548',
publishDate: '20 Feb 2024',
impact: 'Moderate',
score: '6.1',
cvssVector: 'CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N',
severity: 'Medium'
},
{
id: 'CVE-2024-1549',
publishDate: '20 Feb 2024',
impact: 'Moderate',
score: '6.1',
cvssVector: 'CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N',
severity: 'Medium'
}
];

export const ColumnManagementModalDragDropExample: FunctionComponent = () => {
const [ columns, setColumns ] = useState(DEFAULT_COLUMNS);
const [ isOpen, setOpen ] = useState(false);

return (
<>
<ColumnManagementModal
appliedColumns={columns}
applyColumns={(newColumns) => setColumns(newColumns)}
isOpen={isOpen}
onClose={() => setOpen(false)}
enableDragDrop={true}
title="Manage and reorder columns"
description="Selected categories will be displayed in the table. Drag and drop to reorder columns."
/>
<Button
className="pf-v6-u-mb-sm"
onClick={() => setOpen(true)}
variant={ButtonVariant.secondary}
icon={<ColumnsIcon />}
>
Manage columns
</Button>
<Table aria-label="Simple table with reorderable columns" variant="compact">
<Thead>
<Tr>
{columns
.filter((column) => column.isShown)
.map((column) => (
<Th key={column.key}>{column.title}</Th>
))}
</Tr>
</Thead>
<Tbody>
{ROWS.map((row, rowIndex) => (
<Tr key={rowIndex}>
{columns
.filter((column) => column.isShown)
.map((column, columnIndex) => (
<Td key={columnIndex}>{row[column.key]}</Td>
))}
</Tr>
))}
</Tbody>
</Table>
</>
);
};
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import '@testing-library/jest-dom'
import { render, screen, fireEvent } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import ColumnManagementModal, { ColumnManagementModalColumn } from './ColumnManagementModal';

const DEFAULT_COLUMNS : ColumnManagementModalColumn[] = [
Expand Down Expand Up @@ -33,18 +34,29 @@ const DEFAULT_COLUMNS : ColumnManagementModalColumn[] = [
const onClose = jest.fn();
const setColumns = jest.fn();

// Simple mock to track when DragDropSort is used
jest.mock('@patternfly/react-drag-drop', () => ({
DragDropSort: ({ children }) => <div data-testid="drag-drop-sort">{children}</div>,
Droppable: ({ wrapper }) => wrapper,
}));

const renderColumnManagementModal = (props = {}) => render(<ColumnManagementModal
appliedColumns={DEFAULT_COLUMNS}
applyColumns={newColumns => setColumns(newColumns)}
isOpen
onClose={onClose}
data-testid="column-mgmt-modal"
{...props}
/>);

beforeEach(() => {
render(<ColumnManagementModal
appliedColumns={DEFAULT_COLUMNS}
applyColumns={newColumns => setColumns(newColumns)}
isOpen
onClose={onClose}
data-testid="column-mgmt-modal"
/>);
jest.clearAllMocks();
renderColumnManagementModal();
});

const getCheckboxesState = () => {
const checkboxes = screen.getByTestId('column-mgmt-modal').querySelectorAll('input[type="checkbox"]');
// Get only the column checkboxes (exclude the BulkSelect checkbox)
const checkboxes = screen.getByTestId('column-mgmt-modal').querySelectorAll('input[type="checkbox"][data-testid^="column-check-"]');
return (Array.from(checkboxes) as HTMLInputElement[]).map(c => c.checked);
}

Expand All @@ -54,7 +66,7 @@ describe('ColumnManagementModal component', () => {
});

it('should have checkbox checked if column is shown by default', () => {
const idCheckbox = screen.getByTestId('column-mgmt-modal').querySelector('input[type="checkbox"][data-ouia-component-id="ColumnManagementModal-column0-checkbox"]');
const idCheckbox = screen.getByTestId('column-mgmt-modal').querySelector('input[type="checkbox"][data-testid="column-check-id"]');

expect(idCheckbox).toHaveAttribute('disabled');
expect(idCheckbox).toHaveAttribute('checked');
Expand All @@ -72,11 +84,15 @@ describe('ColumnManagementModal component', () => {
expect(getCheckboxesState()).toEqual(DEFAULT_COLUMNS.map(c => c.isShownByDefault));
});

it('should set all columns to show upon clicking on "Select all"', () => {
it('should set all columns to show upon clicking on "Select all"', async () => {
// disable Impact column which is enabled by default
fireEvent.click(screen.getByText('Impact'));

fireEvent.click(screen.getByText('Select all'));
// Use the BulkSelect to select all
const menuToggle = screen.getByLabelText('Bulk select toggle');
await userEvent.click(menuToggle);
const selectAllButton = screen.getByText('Select all (4)');
await userEvent.click(selectAllButton);

expect(getCheckboxesState()).toEqual(DEFAULT_COLUMNS.map(_ => true));
});
Expand All @@ -103,6 +119,23 @@ describe('ColumnManagementModal component', () => {
fireEvent.click(screen.getByText('Cancel'));

expect(onClose).toHaveBeenCalled();
expect(setColumns).toHaveBeenCalledWith(DEFAULT_COLUMNS);
// applyColumns should NOT be called on cancel
expect(setColumns).not.toHaveBeenCalled();
});

describe('enableDragDrop prop', () => {
it('should default enableDragDrop to false', () => {
// Default behavior should not enable drag and drop
expect(screen.queryByTestId('drag-drop-sort')).not.toBeInTheDocument();
});

it('should pass enableDragDrop prop to ListManager', () => {
// Test that the prop is properly passed through to ListManager
jest.clearAllMocks();
renderColumnManagementModal({ enableDragDrop: true });

// When enableDragDrop is true, DragDropSort should be rendered
expect(screen.getByTestId('drag-drop-sort')).toBeInTheDocument();
});
});
});
Loading
Loading