mirror of
https://github.com/ansible/awx.git
synced 2026-03-22 11:25:08 -02:30
Merge pull request #11963 from AlexSCorey/11467-RevertDraagandDrop
Revert "updated patternfly"
This commit is contained in:
@@ -1,18 +1,15 @@
|
|||||||
import React from 'react';
|
import React, { useState } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
DataListAction,
|
|
||||||
DragDrop,
|
|
||||||
Droppable,
|
|
||||||
Draggable,
|
|
||||||
DataListItemRow,
|
|
||||||
DataListItemCells,
|
|
||||||
DataList,
|
DataList,
|
||||||
|
DataListAction,
|
||||||
DataListItem,
|
DataListItem,
|
||||||
DataListCell,
|
DataListCell,
|
||||||
|
DataListItemRow,
|
||||||
DataListControl,
|
DataListControl,
|
||||||
DataListDragButton,
|
DataListDragButton,
|
||||||
|
DataListItemCells,
|
||||||
} from '@patternfly/react-core';
|
} from '@patternfly/react-core';
|
||||||
import { TimesIcon } from '@patternfly/react-icons';
|
import { TimesIcon } from '@patternfly/react-icons';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
@@ -26,85 +23,112 @@ const RemoveActionSection = styled(DataListAction)`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
function DraggableSelectedList({ selected, onRemove, onRowDrag }) {
|
function DraggableSelectedList({ selected, onRemove, onRowDrag }) {
|
||||||
const removeItem = (item) => {
|
const [liveText, setLiveText] = useState('');
|
||||||
onRemove(selected.find((i) => i.name === item));
|
const [id, setId] = useState('');
|
||||||
|
const [isDragging, setIsDragging] = useState(false);
|
||||||
|
|
||||||
|
const onDragStart = (newId) => {
|
||||||
|
setId(newId);
|
||||||
|
setLiveText(t`Dragging started for item id: ${newId}.`);
|
||||||
|
setIsDragging(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
function reorder(list, startIndex, endIndex) {
|
const onDragMove = (oldIndex, newIndex) => {
|
||||||
const result = Array.from(list);
|
setLiveText(
|
||||||
const [removed] = result.splice(startIndex, 1);
|
t`Dragging item ${id}. Item with index ${oldIndex} in now ${newIndex}.`
|
||||||
result.splice(endIndex, 0, removed);
|
);
|
||||||
return result;
|
};
|
||||||
}
|
|
||||||
|
|
||||||
const dragItem = (item, dest) => {
|
const onDragCancel = () => {
|
||||||
if (!dest || item.index === dest.index) {
|
setLiveText(t`Dragging cancelled. List is unchanged.`);
|
||||||
return false;
|
setIsDragging(false);
|
||||||
}
|
};
|
||||||
|
|
||||||
const newItems = reorder(selected, item.index, dest.index);
|
const onDragFinish = (newItemOrder) => {
|
||||||
onRowDrag(newItems);
|
const selectedItems = newItemOrder.map((item) =>
|
||||||
return true;
|
selected.find((i) => i.name === item)
|
||||||
|
);
|
||||||
|
onRowDrag(selectedItems);
|
||||||
|
setIsDragging(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeItem = (item) => {
|
||||||
|
onRemove(selected.find((i) => i.name === item));
|
||||||
};
|
};
|
||||||
|
|
||||||
if (selected.length <= 0) {
|
if (selected.length <= 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const orderedList = selected.map((item) => item?.name);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DragDrop onDrop={dragItem}>
|
<>
|
||||||
<Droppable>
|
<DataList
|
||||||
<DataList data-cy="draggable-list">
|
aria-label={t`Draggable list to reorder and remove selected items.`}
|
||||||
{selected.map(({ name: label, id }, index) => {
|
data-cy="draggable-list"
|
||||||
const rowPosition = index + 1;
|
itemOrder={orderedList}
|
||||||
return (
|
onDragCancel={onDragCancel}
|
||||||
<Draggable value={id} key={rowPosition}>
|
onDragFinish={onDragFinish}
|
||||||
<DataListItem>
|
onDragMove={onDragMove}
|
||||||
<DataListItemRow>
|
onDragStart={onDragStart}
|
||||||
<DataListControl>
|
>
|
||||||
<DataListDragButton
|
{orderedList.map((label, index) => {
|
||||||
isDisabled={selected.length < 2}
|
const rowPosition = index + 1;
|
||||||
data-cy={`reorder-${label}`}
|
return (
|
||||||
/>
|
<DataListItem id={label} key={rowPosition}>
|
||||||
</DataListControl>
|
<DataListItemRow>
|
||||||
<DataListItemCells
|
<DataListControl>
|
||||||
dataListCells={[
|
<DataListDragButton
|
||||||
<DataListCell key={label}>
|
aria-label={t`Reorder`}
|
||||||
<span
|
aria-labelledby={rowPosition}
|
||||||
id={rowPosition}
|
aria-describedby={t`Press space or enter to begin dragging,
|
||||||
>{`${rowPosition}. ${label}`}</span>
|
and use the arrow keys to navigate up or down.
|
||||||
</DataListCell>,
|
Press enter to confirm the drag, or any other key to
|
||||||
]}
|
cancel the drag operation.`}
|
||||||
/>
|
aria-pressed="false"
|
||||||
<RemoveActionSection>
|
data-cy={`reorder-${label}`}
|
||||||
<Button
|
isDisabled={selected.length === 1}
|
||||||
onClick={() => removeItem(label)}
|
/>
|
||||||
variant="plain"
|
</DataListControl>
|
||||||
aria-label={t`Remove`}
|
<DataListItemCells
|
||||||
ouiaId={`draggable-list-remove-${label}`}
|
dataListCells={[
|
||||||
>
|
<DataListCell key={label}>
|
||||||
<TimesIcon />
|
<span id={rowPosition}>{`${rowPosition}. ${label}`}</span>
|
||||||
</Button>
|
</DataListCell>,
|
||||||
</RemoveActionSection>
|
]}
|
||||||
</DataListItemRow>
|
/>
|
||||||
</DataListItem>
|
<RemoveActionSection aria-label={t`Actions`} id={rowPosition}>
|
||||||
</Draggable>
|
<Button
|
||||||
);
|
onClick={() => removeItem(label)}
|
||||||
})}
|
variant="plain"
|
||||||
</DataList>
|
aria-label={t`Remove`}
|
||||||
</Droppable>
|
ouiaId={`draggable-list-remove-${label}`}
|
||||||
</DragDrop>
|
isDisabled={isDragging}
|
||||||
|
>
|
||||||
|
<TimesIcon />
|
||||||
|
</Button>
|
||||||
|
</RemoveActionSection>
|
||||||
|
</DataListItemRow>
|
||||||
|
</DataListItem>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</DataList>
|
||||||
|
<div className="pf-screen-reader" aria-live="assertive">
|
||||||
|
{liveText}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const SelectedListItem = PropTypes.shape({
|
const ListItem = PropTypes.shape({
|
||||||
id: PropTypes.number.isRequired,
|
id: PropTypes.number.isRequired,
|
||||||
name: PropTypes.string.isRequired,
|
name: PropTypes.string.isRequired,
|
||||||
});
|
});
|
||||||
DraggableSelectedList.propTypes = {
|
DraggableSelectedList.propTypes = {
|
||||||
onRemove: PropTypes.func,
|
onRemove: PropTypes.func,
|
||||||
onRowDrag: PropTypes.func,
|
onRowDrag: PropTypes.func,
|
||||||
selected: PropTypes.arrayOf(SelectedListItem),
|
selected: PropTypes.arrayOf(ListItem),
|
||||||
};
|
};
|
||||||
DraggableSelectedList.defaultProps = {
|
DraggableSelectedList.defaultProps = {
|
||||||
onRemove: () => null,
|
onRemove: () => null,
|
||||||
|
|||||||
@@ -1,8 +1,14 @@
|
|||||||
|
// These tests have been turned off because they fail due to a console wanring coming from patternfly.
|
||||||
|
// The warning is that the onDrag api has been deprecated. It's replacement is a DragDrop component,
|
||||||
|
// however that component is not keyboard accessible. Therefore we have elected to turn off these tests.
|
||||||
|
//github.com/patternfly/patternfly-react/issues/6317s
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { act } from 'react-dom/test-utils';
|
||||||
import { mountWithContexts } from '../../../testUtils/enzymeHelpers';
|
import { mountWithContexts } from '../../../testUtils/enzymeHelpers';
|
||||||
import DraggableSelectedList from './DraggableSelectedList';
|
import DraggableSelectedList from './DraggableSelectedList';
|
||||||
|
|
||||||
describe('<DraggableSelectedList />', () => {
|
describe.skip('<DraggableSelectedList />', () => {
|
||||||
let wrapper;
|
let wrapper;
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
jest.clearAllMocks();
|
jest.clearAllMocks();
|
||||||
@@ -27,16 +33,16 @@ describe('<DraggableSelectedList />', () => {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
expect(wrapper.find('DraggableSelectedList').length).toBe(1);
|
expect(wrapper.find('DraggableSelectedList').length).toBe(1);
|
||||||
expect(wrapper.find('Draggable').length).toBe(2);
|
expect(wrapper.find('DataListItem').length).toBe(2);
|
||||||
expect(
|
expect(
|
||||||
wrapper
|
wrapper
|
||||||
.find('Draggable')
|
.find('DataListItem DataListCell')
|
||||||
.first()
|
.first()
|
||||||
.containsMatchingElement(<span>1. foo</span>)
|
.containsMatchingElement(<span>1. foo</span>)
|
||||||
).toEqual(true);
|
).toEqual(true);
|
||||||
expect(
|
expect(
|
||||||
wrapper
|
wrapper
|
||||||
.find('Draggable')
|
.find('DataListItem DataListCell')
|
||||||
.last()
|
.last()
|
||||||
.containsMatchingElement(<span>2. bar</span>)
|
.containsMatchingElement(<span>2. bar</span>)
|
||||||
).toEqual(true);
|
).toEqual(true);
|
||||||
@@ -64,10 +70,64 @@ describe('<DraggableSelectedList />', () => {
|
|||||||
wrapper = mountWithContexts(
|
wrapper = mountWithContexts(
|
||||||
<DraggableSelectedList selected={mockSelected} onRemove={onRemove} />
|
<DraggableSelectedList selected={mockSelected} onRemove={onRemove} />
|
||||||
);
|
);
|
||||||
wrapper.find('Button[aria-label="Remove"]').simulate('click');
|
expect(
|
||||||
|
wrapper
|
||||||
|
.find('DataListDragButton[aria-label="Reorder"]')
|
||||||
|
.prop('isDisabled')
|
||||||
|
).toBe(true);
|
||||||
|
wrapper
|
||||||
|
.find('DataListItem[id="foo"] Button[aria-label="Remove"]')
|
||||||
|
.simulate('click');
|
||||||
expect(onRemove).toBeCalledWith({
|
expect(onRemove).toBeCalledWith({
|
||||||
id: 1,
|
id: 1,
|
||||||
name: 'foo',
|
name: 'foo',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should disable remove button when dragging item', () => {
|
||||||
|
const mockSelected = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: 'foo',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: 'bar',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
wrapper = mountWithContexts(
|
||||||
|
<DraggableSelectedList
|
||||||
|
selected={mockSelected}
|
||||||
|
onRemove={() => {}}
|
||||||
|
onRowDrag={() => {}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
wrapper.find('Button[aria-label="Remove"]').at(0).prop('isDisabled')
|
||||||
|
).toBe(false);
|
||||||
|
expect(
|
||||||
|
wrapper.find('Button[aria-label="Remove"]').at(1).prop('isDisabled')
|
||||||
|
).toBe(false);
|
||||||
|
act(() => {
|
||||||
|
wrapper.find('DataList').prop('onDragStart')();
|
||||||
|
});
|
||||||
|
wrapper.update();
|
||||||
|
expect(
|
||||||
|
wrapper.find('Button[aria-label="Remove"]').at(0).prop('isDisabled')
|
||||||
|
).toBe(true);
|
||||||
|
expect(
|
||||||
|
wrapper.find('Button[aria-label="Remove"]').at(1).prop('isDisabled')
|
||||||
|
).toBe(true);
|
||||||
|
act(() => {
|
||||||
|
wrapper.find('DataList').prop('onDragCancel')();
|
||||||
|
});
|
||||||
|
wrapper.update();
|
||||||
|
expect(
|
||||||
|
wrapper.find('Button[aria-label="Remove"]').at(0).prop('isDisabled')
|
||||||
|
).toBe(false);
|
||||||
|
expect(
|
||||||
|
wrapper.find('Button[aria-label="Remove"]').at(1).prop('isDisabled')
|
||||||
|
).toBe(false);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -44,9 +44,9 @@ describe('JobOutputSearch', () => {
|
|||||||
wrapper.find(searchBtn).simulate('click');
|
wrapper.find(searchBtn).simulate('click');
|
||||||
});
|
});
|
||||||
expect(wrapper.find('Search').prop('columns')).toHaveLength(3);
|
expect(wrapper.find('Search').prop('columns')).toHaveLength(3);
|
||||||
expect(wrapper.find('Search').prop('columns').at(0).name).toBe('Stdout');
|
expect(wrapper.find('Search').prop('columns')[0].name).toBe('Stdout');
|
||||||
expect(wrapper.find('Search').prop('columns').at(1).name).toBe('Event');
|
expect(wrapper.find('Search').prop('columns')[1].name).toBe('Event');
|
||||||
expect(wrapper.find('Search').prop('columns').at(2).name).toBe('Advanced');
|
expect(wrapper.find('Search').prop('columns')[2].name).toBe('Advanced');
|
||||||
expect(history.location.search).toEqual('?stdout__icontains=99');
|
expect(history.location.search).toEqual('?stdout__icontains=99');
|
||||||
});
|
});
|
||||||
test('Should not have Event key in search drop down for system job', () => {
|
test('Should not have Event key in search drop down for system job', () => {
|
||||||
@@ -70,8 +70,8 @@ describe('JobOutputSearch', () => {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
expect(wrapper.find('Search').prop('columns')).toHaveLength(2);
|
expect(wrapper.find('Search').prop('columns')).toHaveLength(2);
|
||||||
expect(wrapper.find('Search').prop('columns').at(0).name).toBe('Stdout');
|
expect(wrapper.find('Search').prop('columns')[0].name).toBe('Stdout');
|
||||||
expect(wrapper.find('Search').prop('columns').at(1).name).toBe('Advanced');
|
expect(wrapper.find('Search').prop('columns')[1].name).toBe('Advanced');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Should not have Event key in search drop down for inventory update job', () => {
|
test('Should not have Event key in search drop down for inventory update job', () => {
|
||||||
@@ -94,8 +94,9 @@ describe('JobOutputSearch', () => {
|
|||||||
context: { router: { history } },
|
context: { router: { history } },
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(wrapper.find('Search').prop('columns')).toHaveLength(2);
|
expect(wrapper.find('Search').prop('columns')).toHaveLength(2);
|
||||||
expect(wrapper.find('Search').prop('columns').at(0).name).toBe('Stdout');
|
expect(wrapper.find('Search').prop('columns')[0].name).toBe('Stdout');
|
||||||
expect(wrapper.find('Search').prop('columns').at(1).name).toBe('Advanced');
|
expect(wrapper.find('Search').prop('columns')[1].name).toBe('Advanced');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user