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
15 changes: 8 additions & 7 deletions packages/components/src/ConditionalFilter/GroupFilter.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// @ts-nocheck
import React, { useEffect, useRef, useState } from 'react';
import classNames from 'classnames';
import { Button } from '@patternfly/react-core/dist/dynamic/components/Button';
Expand Down Expand Up @@ -148,9 +149,9 @@ const GroupFilter: React.FunctionComponent<GroupFilterProps> = (props) => {
onChange,
calculateSelected(selected || {})
);
const groupMenuItems = getGroupMenuItems(groups, onChange, calculateSelected(selected || {}));
const groupMenuItems = getGroupMenuItems(groups, onChange, calculateSelected(selected || {}, groups));

const renderItem = ({ groupSelectable, ...item }: GroupFilterItem, key: string | number, type?: GroupType, groupKey = '') => (
const renderItem = ({ groupSelectable, ...item }: GroupFilterItem, key: string | number, type?: GroupType, groupKey = '', selected) => (
<MenuItem
itemId={key}
key={`${item.value}-${key}-item`}
Expand All @@ -174,7 +175,7 @@ const GroupFilter: React.FunctionComponent<GroupFilterProps> = (props) => {
<Checkbox
{...item}
label={item?.label}
isChecked={item?.isChecked || isChecked(groupKey, item?.value || key, item?.id, item?.tagValue, selected || {}) || false}
isChecked={item?.isChecked || isChecked(groupKey, item?.value || key, item?.id, item?.tagValue, selected || {})}
onChange={item.onChange}
onClick={
item.onClick
Expand Down Expand Up @@ -207,14 +208,14 @@ const GroupFilter: React.FunctionComponent<GroupFilterProps> = (props) => {
</MenuItem>
);

const renderItems = (items: GroupFilterItem[], type?: GroupType, groupKey = '') =>
const renderItems = (items: GroupFilterItem[], type?: GroupType, groupKey = '', selected) =>
items.map((item, key) =>
(type || item.type) === GroupType.treeView ? (
<div key={`${item.value}-${key}-item`} className="ins-c-tree-view">
{renderItem(item as TreeViewItem, key, type, groupKey)}
{renderItem(item as TreeViewItem, key, type, groupKey, selected)}
</div>
) : (
renderItem(item, key, type, groupKey)
renderItem(item, key, type, groupKey, selected)
)
);

Expand Down Expand Up @@ -286,7 +287,7 @@ const GroupFilter: React.FunctionComponent<GroupFilterProps> = (props) => {
label={!(group as Group).groupSelectable && typeof group.label === 'string' ? group.label : undefined}
key={`${group.label}-${groupKey}-group`}
>
{group.items && renderItems(group.items, group.type, group.value)}
{group.items && renderItems(group.items, group.type, group.value, selected)}
</MenuGroup>
))}
{onShowMore ? (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ describe('calculateSelected - treeView', () => {

it('should calculate selected properly, checked = false', () => {
const result = calculateSelected({ '': { item1: true, item2: true } })('treeView', '', tree, false);
const expectedResult = { '': { item1: false, item2: false } };
const expectedResult = { '': { '': false, item1: false, item2: false } };
expect(result).toEqual(expectedResult);
});

Expand Down
76 changes: 63 additions & 13 deletions packages/components/src/ConditionalFilter/groupFilterConstants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,12 +127,8 @@ export const isChecked = (
itemValue: string | number,
id: string | undefined,
tagValue: string | undefined,
propSelected: Record<string, Record<string, boolean | GroupItem>>
selected: Record<string, Record<string, boolean | GroupItem>>
) => {
const selected = {
...propSelected,
};

if (typeof selected[groupValue] === 'undefined') {
return false;
}
Expand All @@ -147,10 +143,10 @@ export const isChecked = (
}
}

return Boolean(group.isSelected);
return group.isSelected;
}

return Boolean(selected[groupValue][itemValue]);
return selected[groupValue][itemValue];
};

export type FilterMenuItemOnChange = (
Expand Down Expand Up @@ -210,7 +206,8 @@ export const getMenuItems = (
string
] = [
event,
calculateSelected(groupType || item.type, groupValue, (groupType || item.type) === GroupType.treeView ? treeViewItem : item.value, checked),
// @ts-ignore
calculateSelected(groupType || item.type, groupValue, (groupType || item.type) === GroupType.treeView ? treeViewItem : item.value, (event.target as HTMLInputElement)?.checked || checked ),
{
value: groupValue,
id: (groupId || item.id) as string,
Expand Down Expand Up @@ -281,10 +278,27 @@ export const getGroupMenuItems = (
return result.filter(({ noFilter, items = [] }) => !noFilter || items.length > 0);
};

const isGroupSelected = (selectedCount, groupItemCount) => {
if (selectedCount === 0) {
return false
}

if (selectedCount < groupItemCount) {
return null
}

if (selectedCount === groupItemCount) {
return true
}
}

export const calculateSelected =
(selectedTags: Record<string, Record<string, GroupItem | boolean>>) =>
(selectedTags: Record<string, Record<string, GroupItem | boolean>>, groups?: Group[]) =>
(type = GroupType.button, groupKey = '', value: TreeViewItem | string = '', checked = false) => {
const activeGroup = selectedTags?.[groupKey];
const groupItems = groups?.find(({label}) => label === groupKey)?.items
const groupItemsCount = groupItems?.length
const activeGroupGroupValue = value === groupKey ? checked : undefined
const children =
type === GroupType.treeView
? [value as TreeViewItem].reduce(function iter(acc: TreeViewItem[], curr: TreeViewItem): TreeViewItem[] {
Expand All @@ -298,6 +312,25 @@ export const calculateSelected =
: [];

const itemKeys = type === GroupType.treeView ? children.map((item: TreeViewItem) => item.id) : [String(value)];
const itemKeysCount = itemKeys.filter((key) => key !== groupKey).length

if ( activeGroupGroupValue === true || activeGroupGroupValue === false) {
const result = groupItems?.map(({value}) => value).reduce((result, itemValue) => ({
...result,
[groupKey]: {
...result[groupKey],
[itemValue]: activeGroupGroupValue
}
}), selectedTags|| {})

return {
...result,
[groupKey]: {
...result?.[groupKey] || {},
[groupKey]: activeGroupGroupValue
}
}
}

if (activeGroup) {
let result = selectedTags;
Expand All @@ -324,10 +357,18 @@ export const calculateSelected =
};
}
});
return result;
const selectedItemsCount = Object.entries(result[groupKey]).filter(([key ,value]) => key !== groupKey && Boolean(value) === true).length

return {
...result,
[groupKey]: {
...result[groupKey],
[groupKey]: isGroupSelected(selectedItemsCount, groupItemsCount)
}
};
}

return itemKeys.reduce(
const result = itemKeys.reduce(
(acc, curr) => ({
...acc,
[groupKey]: {
Expand All @@ -337,17 +378,26 @@ export const calculateSelected =
}),
selectedTags
);
const selectedItemsCount = Object.entries(result[groupKey]).filter(([key,value]) => key !== groupKey && Boolean(value) === true).length

return {
...result,
[groupKey]: {
...result[groupKey],
[groupKey]: isGroupSelected(selectedItemsCount, groupItemsCount)
}
};
};

const areAllChildrenChecked = (dataItem: TreeViewItem, groupKey: string, selected: Record<string, Record<string, boolean | GroupItem>>): boolean =>
dataItem.children
? dataItem.children.every((child: TreeViewItem) => areAllChildrenChecked(child, groupKey, selected))
: isChecked(groupKey, dataItem.id || '', undefined, undefined, selected);
: isChecked(groupKey, dataItem.id || '', undefined, undefined, selected) || false;

const areSomeChildrenChecked = (dataItem: TreeViewItem, groupKey: string, selected: Record<string, Record<string, boolean | GroupItem>>): boolean =>
dataItem.children
? dataItem.children.some((child: TreeViewItem) => areSomeChildrenChecked(child, groupKey, selected))
: isChecked(groupKey, dataItem.id || '', undefined, undefined, selected);
: isChecked(groupKey, dataItem.id || '', undefined, undefined, selected) || false;

export const mapTree = (item: TreeViewItem, groupKey: string, selected: Record<string, Record<string, boolean | GroupItem>>): TreeViewItem => {
const hasCheck = areAllChildrenChecked(item, groupKey, selected);
Expand Down
3 changes: 3 additions & 0 deletions packages/components/src/FilterChips/FilterChips.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ describe('FilterChips component', () => {
{
name: 'Chip 1',
},
{
name: 'Chip 2',
},
],
};
const { container } = render(<FilterChips filters={[...filters, newGroup]} onDeleteGroup={onDelete} />);
Expand Down
2 changes: 1 addition & 1 deletion packages/components/src/FilterChips/FilterChips.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ const FilterChips: React.FunctionComponent<FilterChipsProps> = ({
<ChipGroup
key={`group_${group.category}`}
categoryName={String(group.category) || ' '}
{...(onDeleteGroup && {
{...(group.chips.length > 1 && onDeleteGroup && {
isClosable: true,
onClick: (event) => {
event.stopPropagation();
Expand Down