Skip to content

Commit e7fee69

Browse files
committed
fix(group-filter): restore proper groupSelectable behaviour
1 parent dfe7db4 commit e7fee69

File tree

4 files changed

+75
-21
lines changed

4 files changed

+75
-21
lines changed

packages/components/src/ConditionalFilter/GroupFilter.tsx

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// @ts-nocheck
12
import React, { useEffect, useRef, useState } from 'react';
23
import classNames from 'classnames';
34
import { Button } from '@patternfly/react-core/dist/dynamic/components/Button';
@@ -148,9 +149,9 @@ const GroupFilter: React.FunctionComponent<GroupFilterProps> = (props) => {
148149
onChange,
149150
calculateSelected(selected || {})
150151
);
151-
const groupMenuItems = getGroupMenuItems(groups, onChange, calculateSelected(selected || {}));
152+
const groupMenuItems = getGroupMenuItems(groups, onChange, calculateSelected(selected || {}, groups));
152153

153-
const renderItem = ({ groupSelectable, ...item }: GroupFilterItem, key: string | number, type?: GroupType, groupKey = '') => (
154+
const renderItem = ({ groupSelectable, ...item }: GroupFilterItem, key: string | number, type?: GroupType, groupKey = '', selected) => (
154155
<MenuItem
155156
itemId={key}
156157
key={`${item.value}-${key}-item`}
@@ -174,7 +175,7 @@ const GroupFilter: React.FunctionComponent<GroupFilterProps> = (props) => {
174175
<Checkbox
175176
{...item}
176177
label={item?.label}
177-
isChecked={item?.isChecked || isChecked(groupKey, item?.value || key, item?.id, item?.tagValue, selected || {}) || false}
178+
isChecked={item?.isChecked || isChecked(groupKey, item?.value || key, item?.id, item?.tagValue, selected || {})}
178179
onChange={item.onChange}
179180
onClick={
180181
item.onClick
@@ -207,14 +208,14 @@ const GroupFilter: React.FunctionComponent<GroupFilterProps> = (props) => {
207208
</MenuItem>
208209
);
209210

210-
const renderItems = (items: GroupFilterItem[], type?: GroupType, groupKey = '') =>
211+
const renderItems = (items: GroupFilterItem[], type?: GroupType, groupKey = '', selected) =>
211212
items.map((item, key) =>
212213
(type || item.type) === GroupType.treeView ? (
213214
<div key={`${item.value}-${key}-item`} className="ins-c-tree-view">
214-
{renderItem(item as TreeViewItem, key, type, groupKey)}
215+
{renderItem(item as TreeViewItem, key, type, groupKey, selected)}
215216
</div>
216217
) : (
217-
renderItem(item, key, type, groupKey)
218+
renderItem(item, key, type, groupKey, selected)
218219
)
219220
);
220221

@@ -286,7 +287,7 @@ const GroupFilter: React.FunctionComponent<GroupFilterProps> = (props) => {
286287
label={!(group as Group).groupSelectable && typeof group.label === 'string' ? group.label : undefined}
287288
key={`${group.label}-${groupKey}-group`}
288289
>
289-
{group.items && renderItems(group.items, group.type, group.value)}
290+
{group.items && renderItems(group.items, group.type, group.value, selected)}
290291
</MenuGroup>
291292
))}
292293
{onShowMore ? (

packages/components/src/ConditionalFilter/groupFilterConstants.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ describe('calculateSelected - treeView', () => {
8585

8686
it('should calculate selected properly, checked = false', () => {
8787
const result = calculateSelected({ '': { item1: true, item2: true } })('treeView', '', tree, false);
88-
const expectedResult = { '': { item1: false, item2: false } };
88+
const expectedResult = { '': { '': false, item1: false, item2: false } };
8989
expect(result).toEqual(expectedResult);
9090
});
9191

packages/components/src/ConditionalFilter/groupFilterConstants.ts

Lines changed: 63 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -127,12 +127,8 @@ export const isChecked = (
127127
itemValue: string | number,
128128
id: string | undefined,
129129
tagValue: string | undefined,
130-
propSelected: Record<string, Record<string, boolean | GroupItem>>
130+
selected: Record<string, Record<string, boolean | GroupItem>>
131131
) => {
132-
const selected = {
133-
...propSelected,
134-
};
135-
136132
if (typeof selected[groupValue] === 'undefined') {
137133
return false;
138134
}
@@ -147,10 +143,10 @@ export const isChecked = (
147143
}
148144
}
149145

150-
return Boolean(group.isSelected);
146+
return group.isSelected;
151147
}
152148

153-
return Boolean(selected[groupValue][itemValue]);
149+
return selected[groupValue][itemValue];
154150
};
155151

156152
export type FilterMenuItemOnChange = (
@@ -210,7 +206,8 @@ export const getMenuItems = (
210206
string
211207
] = [
212208
event,
213-
calculateSelected(groupType || item.type, groupValue, (groupType || item.type) === GroupType.treeView ? treeViewItem : item.value, checked),
209+
// @ts-ignore
210+
calculateSelected(groupType || item.type, groupValue, (groupType || item.type) === GroupType.treeView ? treeViewItem : item.value, (event.target as HTMLInputElement)?.checked || checked ),
214211
{
215212
value: groupValue,
216213
id: (groupId || item.id) as string,
@@ -281,10 +278,27 @@ export const getGroupMenuItems = (
281278
return result.filter(({ noFilter, items = [] }) => !noFilter || items.length > 0);
282279
};
283280

281+
const isGroupSelected = (selectedCount, groupItemCount) => {
282+
if (selectedCount === 0) {
283+
return false
284+
}
285+
286+
if (selectedCount < groupItemCount) {
287+
return null
288+
}
289+
290+
if (selectedCount === groupItemCount) {
291+
return true
292+
}
293+
}
294+
284295
export const calculateSelected =
285-
(selectedTags: Record<string, Record<string, GroupItem | boolean>>) =>
296+
(selectedTags: Record<string, Record<string, GroupItem | boolean>>, groups?: Group[]) =>
286297
(type = GroupType.button, groupKey = '', value: TreeViewItem | string = '', checked = false) => {
287298
const activeGroup = selectedTags?.[groupKey];
299+
const groupItems = groups?.find(({label}) => label === groupKey)?.items
300+
const groupItemsCount = groupItems?.length
301+
const activeGroupGroupValue = value === groupKey ? checked : undefined
288302
const children =
289303
type === GroupType.treeView
290304
? [value as TreeViewItem].reduce(function iter(acc: TreeViewItem[], curr: TreeViewItem): TreeViewItem[] {
@@ -298,6 +312,25 @@ export const calculateSelected =
298312
: [];
299313

300314
const itemKeys = type === GroupType.treeView ? children.map((item: TreeViewItem) => item.id) : [String(value)];
315+
const itemKeysCount = itemKeys.filter((key) => key !== groupKey).length
316+
317+
if ( activeGroupGroupValue === true || activeGroupGroupValue === false) {
318+
const result = groupItems?.map(({value}) => value).reduce((result, itemValue) => ({
319+
...result,
320+
[groupKey]: {
321+
...result[groupKey],
322+
[itemValue]: activeGroupGroupValue
323+
}
324+
}), selectedTags|| {})
325+
326+
return {
327+
...result,
328+
[groupKey]: {
329+
...result?.[groupKey] || {},
330+
[groupKey]: activeGroupGroupValue
331+
}
332+
}
333+
}
301334

302335
if (activeGroup) {
303336
let result = selectedTags;
@@ -324,10 +357,18 @@ export const calculateSelected =
324357
};
325358
}
326359
});
327-
return result;
360+
const selectedItemsCount = Object.entries(result[groupKey]).filter(([key ,value]) => key !== groupKey && Boolean(value) === true).length
361+
362+
return {
363+
...result,
364+
[groupKey]: {
365+
...result[groupKey],
366+
[groupKey]: isGroupSelected(selectedItemsCount, groupItemsCount)
367+
}
368+
};
328369
}
329370

330-
return itemKeys.reduce(
371+
const result = itemKeys.reduce(
331372
(acc, curr) => ({
332373
...acc,
333374
[groupKey]: {
@@ -337,17 +378,26 @@ export const calculateSelected =
337378
}),
338379
selectedTags
339380
);
381+
const selectedItemsCount = Object.entries(result[groupKey]).filter(([key,value]) => key !== groupKey && Boolean(value) === true).length
382+
383+
return {
384+
...result,
385+
[groupKey]: {
386+
...result[groupKey],
387+
[groupKey]: isGroupSelected(selectedItemsCount, groupItemsCount)
388+
}
389+
};
340390
};
341391

342392
const areAllChildrenChecked = (dataItem: TreeViewItem, groupKey: string, selected: Record<string, Record<string, boolean | GroupItem>>): boolean =>
343393
dataItem.children
344394
? dataItem.children.every((child: TreeViewItem) => areAllChildrenChecked(child, groupKey, selected))
345-
: isChecked(groupKey, dataItem.id || '', undefined, undefined, selected);
395+
: isChecked(groupKey, dataItem.id || '', undefined, undefined, selected) || false;
346396

347397
const areSomeChildrenChecked = (dataItem: TreeViewItem, groupKey: string, selected: Record<string, Record<string, boolean | GroupItem>>): boolean =>
348398
dataItem.children
349399
? dataItem.children.some((child: TreeViewItem) => areSomeChildrenChecked(child, groupKey, selected))
350-
: isChecked(groupKey, dataItem.id || '', undefined, undefined, selected);
400+
: isChecked(groupKey, dataItem.id || '', undefined, undefined, selected) || false;
351401

352402
export const mapTree = (item: TreeViewItem, groupKey: string, selected: Record<string, Record<string, boolean | GroupItem>>): TreeViewItem => {
353403
const hasCheck = areAllChildrenChecked(item, groupKey, selected);

packages/components/src/FilterChips/FilterChips.test.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,9 @@ describe('FilterChips component', () => {
9898
{
9999
name: 'Chip 1',
100100
},
101+
{
102+
name: 'Chip 2',
103+
},
101104
],
102105
};
103106
const { container } = render(<FilterChips filters={[...filters, newGroup]} onDeleteGroup={onDelete} />);

0 commit comments

Comments
 (0)