Skip to content

Commit

Permalink
fix(DualList): Add item disability functionality. (patternfly#1071)
Browse files Browse the repository at this point in the history
  • Loading branch information
ronlavi2412 authored and jeff-phillips-18 committed Dec 18, 2018
1 parent 1430bda commit ddc0e8e
Show file tree
Hide file tree
Showing 8 changed files with 137 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -117,12 +117,22 @@
color: white;
}

&.disabled {
cursor: not-allowed;
background: @color-pf-black-150;
color: @color-pf-black-500;

input[type='checkbox'] {
cursor: not-allowed;
}
}

&.child {
padding-left: 22px;
}

&:hover {
&:not(.selected) {
&:not(.selected):not(.disabled) {
background-color: @color-pf-blue-100;
color: inherit;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,12 +117,22 @@ $dual-list-scroll-bar-length: 12px;
color: white;
}

&.disabled {
cursor: not-allowed;
background: $color-pf-black-150;
color: $color-pf-black-500;

input[type='checkbox'] {
cursor: not-allowed;
}
}

&.child {
padding-left: 22px;
}

&:hover {
&:not(.selected) {
&:not(.selected):not(.disabled) {
background-color: $color-pf-blue-100;
color: inherit;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,11 @@ import {
isAllItemsChecked,
isItemExistOnList,
filterByHiding,
getItemsLength,
toggleFilterredItems,
getFilterredItemsLength,
makeAllItemsVisible,
getSelectedFilterredItemsLength,
isItemSelected
isItemSelected,
getFilterredItems
} from './helpers';

class DualList extends React.Component {
Expand Down Expand Up @@ -81,11 +80,12 @@ class DualList extends React.Component {
const items = cloneDeep(originalItems);
let selectCount = originalSelectCount;
if (filterTerm) {
toggleFilterredItems(items, checked);
selectCount += getFilterredItemsLength(items) * (checked ? 1 : -1);
const filterredItems = getFilterredItems(items);
const toggledAmount = toggleAllItems(filterredItems, checked);
selectCount += toggledAmount * (checked ? 1 : -1);
} else {
toggleAllItems(items, checked);
selectCount = checked ? getItemsLength(items) : 0;
const toggledAmount = toggleAllItems(items, checked);
selectCount = checked ? selectCount + toggledAmount : 0;
}
this.props.onMainCheckboxChange({
side,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ const getProps = () => ({
{ value: 'Heather Davis', label: 'Heather Davis' }
]
},
right: { items: [{ value: 'Donald Trump', label: 'Donald Trump' }] }
right: {
items: [{ value: 'Donald Trump', label: 'Donald Trump' }]
}
});

test('dual-list render properly ', () => {
Expand Down Expand Up @@ -170,3 +172,16 @@ test('sorting works ! ', () => {
sortingIcon.simulate('click', mockedEvent);
expect(component.state().left.items[0]).toBe(originalList[originalList.length - 1]);
});

test('item is disabled and tooltip exists', () => {
const props = getProps();
props.right.items.push({
value: 'Barack Obama',
label: 'Barack Obama',
disabled: true,
tooltipText: 'Barack Obama'
});
const component = mount(<DualListControlled {...props} />);
expect(component.exists('DualListItemTooltip')).toBeTruthy();
expect(component.exists('.disabled')).toBeTruthy();
});
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { MenuItem } from '../../index';

export const items = {
left: [
{ value: 'Ann Little', label: 'Ann Little' },
{ value: 'Ann Little', label: 'Ann Little', disabled: true, tooltipText: 'Permission Denied' },
{ value: 'Daniel Nguyen', label: 'Daniel Nguyen' },
{ value: 'Heather Davis', label: 'Heather Davis' },
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import DualListItemTooltip from './DualListItemTooltip';
import { TypeAheadSelect } from '../../../components/TypeAheadSelect';
import { noop } from '../../../common/helpers';

Expand All @@ -16,10 +17,18 @@ const DualListItem = ({
filterTerm,
onChange,
side,
hidden
hidden,
disabled,
tooltipID,
tooltipText
}) => {
const cx = classNames('dual-list-pf-item', className, checked && ' selected');
return (
const cx = classNames('dual-list-pf-item', className, checked && 'selected', disabled && 'disabled');
const itemLabel = (
<span className="dual-list-pf-item-label">
<Highlighter search={filterTerm}>{label}</Highlighter>
</span>
);
const item = (
<label className={cx} hidden={hidden}>
<input
type="checkbox"
Expand All @@ -29,12 +38,26 @@ const DualListItem = ({
checked={checked || false}
value={value}
data-side={side}
disabled={disabled}
/>
<span className="dual-list-pf-item-label">
<Highlighter search={filterTerm}>{label}</Highlighter>
</span>
{itemLabel}
</label>
);
const getTooltipID = () => {
let uniqueTooltipID = `dual-list-item-tooltip-${side}`;
if (parentPosition) {
uniqueTooltipID += `-${parentPosition}`;
}
uniqueTooltipID += `-${position}`;
return uniqueTooltipID;
};
return tooltipText ? (
<DualListItemTooltip text={tooltipText} id={tooltipID || getTooltipID()}>
{item}
</DualListItemTooltip>
) : (
item
);
};

DualListItem.propTypes = {
Expand All @@ -57,7 +80,13 @@ DualListItem.propTypes = {
/** The side of the selector. */
side: PropTypes.string,
/** Sets the item visibillity when filtering. */
hidden: PropTypes.bool
hidden: PropTypes.bool,
/** Disable the item to move between lists */
disabled: PropTypes.bool,
/** unique tooltip ID */
tooltipID: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
/** text to be shown on the tooltip */
tooltipText: PropTypes.string
};

DualListItem.defaultProps = {
Expand All @@ -70,7 +99,10 @@ DualListItem.defaultProps = {
filterTerm: null,
onChange: noop,
side: null,
hidden: false
hidden: false,
disabled: false,
tooltipID: null,
tooltipText: null
};

export default DualListItem;
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from 'react';
import PropTypes from 'prop-types';
import { OverlayTrigger, Tooltip } from '../../../index';

const DualListItemTooltip = ({ id, text, children }) => {
const tooltip = <Tooltip id={id}>{text}</Tooltip>;
return (
<OverlayTrigger overlay={tooltip} placement="top" trigger={['hover', 'focus']} delayShow={150}>
{children}
</OverlayTrigger>
);
};

DualListItemTooltip.propTypes = {
/** unique tooltip ID */
id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
/** text to be shown on the tooltip */
text: PropTypes.string,
/** children nodes */
children: PropTypes.node
};

DualListItemTooltip.defaultProps = {
id: null,
text: null,
children: null
};

export default DualListItemTooltip;
Original file line number Diff line number Diff line change
Expand Up @@ -155,15 +155,29 @@ export const itemHasChildren = item => item.children !== undefined;
export const getItemPosition = (array, position, isSortAsc) => (isSortAsc ? position : array.length - position - 1);

export const toggleAllItems = (list, checked) => {
let toggleCount = 0;
list.forEach(item => {
item.checked = checked;
if (item.disabled) {
return;
}
if (item.checked !== checked) {
item.checked = checked;
toggleCount += 1;
}
if (itemHasChildren(item)) {
let childrenToggleCount = 0;
item.children.forEach(childItem => {
childItem.checked = checked;
if (childItem.checked !== checked) {
childItem.checked = checked;
childrenToggleCount += 1;
}
});
if (childrenToggleCount > 0) {
toggleCount += childrenToggleCount - 1;
}
}
return item;
});
return toggleCount;
};

export const isAllItemsChecked = (items, selectCount) => selectCount > 0 && selectCount === getItemsLength(items);
Expand All @@ -179,24 +193,7 @@ export const isItemExistOnList = (list, itemLabel) => {
return { isParentExist: parentIndex !== null, parentIndex };
};

export const toggleFilterredItems = (list, checked) => {
list.forEach(item => {
if (!isItemHidden(item)) {
item.checked = checked;
if (itemHasChildren(item)) {
toggleAllItems(item.children, checked);
}
} else if (itemHasChildren(item)) {
item.children.forEach(childItem => {
if (!isItemHidden(childItem)) {
item.checked = checked;
}
});
}
});
};

export const getFilteredItems = list => {
export const getFilterredItems = list => {
const filteredItems = [];
list.forEach(item => {
if (!isItemHidden(item)) {
Expand All @@ -217,10 +214,10 @@ export const getFilteredItems = list => {
return filteredItems;
};

export const getFilterredItemsLength = list => getItemsLength(getFilteredItems(list));
export const getFilterredItemsLength = list => getItemsLength(getFilterredItems(list));

export const getSelectedFilterredItemsLength = list => {
const filteredItems = getFilteredItems(list);
const filteredItems = getFilterredItems(list);
let selectedAmount = 0;
filteredItems.forEach(item => {
if (isItemSelected(item)) {
Expand All @@ -244,3 +241,5 @@ export const getSelectedFilterredItemsLength = list => {
export const isItemSelected = item => item.checked;

export const isItemHidden = item => item.hidden;

export const isItemDisabled = item => item.disabled;

0 comments on commit ddc0e8e

Please sign in to comment.