@rh-support/cases 2.1.69 → 2.1.70
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/esm/components/case-list/case-list-filters/AccountsBookmarkedGroupFilter.js +2 -2
- package/lib/esm/components/case-list/case-list-filters/CreatorSsoNameFilter.js +1 -1
- package/lib/esm/components/case-list/case-list-filters/GroupsFilter.d.ts.map +1 -1
- package/lib/esm/components/case-list/case-list-filters/GroupsFilter.js +156 -27
- package/lib/esm/scss/_pf-overrides.scss +19 -0
- package/package.json +4 -4
|
@@ -98,6 +98,6 @@ export function AccountsBookmarkedGroupFilter(props) {
|
|
|
98
98
|
return null;
|
|
99
99
|
}
|
|
100
100
|
return (React.createElement("div", { className: "pf-v5-c-select" },
|
|
101
|
-
React.createElement("label", { htmlFor: "case-list-
|
|
102
|
-
React.createElement(Select, { variant: SelectVariant.typeaheadMulti, onToggle: (_event, open) => onBookmarksToggle(open), onSelect: onBookmarksSelect, onClear: onBookmarksClear, isOpen: isOpen, onFilter: onBookmarksFilter, placeholderText: getDropdownBtnPlaceholder(t(canAccessManagedAccounts ? 'Select an account' : 'Search for a bookmark'), canAccessManagedAccounts ? selectedAccounts : selectedBookmarks, '', dropdownOptions.length, canAccessManagedAccounts ? t('All accounts') : t('All bookmarks')), "data-tracking-id": "accounts-filter", id: "case-list-
|
|
101
|
+
React.createElement("label", { htmlFor: "case-list-account-filter", className: "case-list-account-filter-label" }, canAccessManagedAccounts ? t('Accounts') : t(filterNamesMap[SolrKeys.accountNumber])),
|
|
102
|
+
React.createElement(Select, { variant: SelectVariant.typeaheadMulti, onToggle: (_event, open) => onBookmarksToggle(open), onSelect: onBookmarksSelect, onClear: onBookmarksClear, isOpen: isOpen, onFilter: onBookmarksFilter, placeholderText: getDropdownBtnPlaceholder(t(canAccessManagedAccounts ? 'Select an account' : 'Search for a bookmark'), canAccessManagedAccounts ? selectedAccounts : selectedBookmarks, '', dropdownOptions.length, canAccessManagedAccounts ? t('All accounts') : t('All bookmarks')), "data-tracking-id": "accounts-filter", id: "case-list-account-filter" }, getBookmarksOptions(dropdownOptions))));
|
|
103
103
|
}
|
|
@@ -209,7 +209,7 @@ export function CreatorSsoNameFilter() {
|
|
|
209
209
|
React.createElement(TextInputGroupMain, { value: externalQuery, onClick: onExternalToggle, onKeyDown: onInputKeyDown, placeholder: getDropdownBtnPlaceholder(t('Search for a name'), selectedExternalContacts.map((i) => i.label), ' ', filteredOptions.length + dropdownHeader.length, t('All contacts')), onChange: onExternalQueryChange, isExpanded: isExternalOpen, innerRef: externalInputRef, "aria-controls": "external-ssousername-filter", role: "combobox" }),
|
|
210
210
|
React.createElement(TextInputGroupUtilities, null, !isEmpty(externalQuery) && (React.createElement(Button, { variant: "plain", onClick: () => setExternalQuery(''), isDisabled: isFetchingExternalContacts, "aria-label": t('Clear') }, isFetchingExternalContacts ? (React.createElement(LoadingIndicator, { show: true, size: "sm" })) : (React.createElement(TimesCircleIcon, { "aria-hidden": true }))))))));
|
|
211
211
|
return (React.createElement("div", null,
|
|
212
|
-
React.createElement("label", { htmlFor: "case-list-username-filter" },
|
|
212
|
+
React.createElement("label", { htmlFor: "case-list-username-filter", className: "case-list-username-filter-label" },
|
|
213
213
|
React.createElement(Trans, null, filterNamesMap['usernameFilterTitle'])),
|
|
214
214
|
!loggedInUserRights.data.isInternal() ? (React.createElement(Select, { id: "external-ssousername-filter", "data-tracking-id": "external-ssousername-filter", isOpen: isExternalOpen, onOpenChange: () => setIsExternalOpen(false), toggle: externalToggle, popperProps: { direction: 'down', enableFlip: false }, isScrollable: true, onSelect: (_e, v) => onSelectExternal(v) },
|
|
215
215
|
React.createElement(SelectList, null, filteredExternalList))) : (React.createElement(InternalSsoNameFilter, null))));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GroupsFilter.d.ts","sourceRoot":"","sources":["../../../../../src/components/case-list/case-list-filters/GroupsFilter.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"GroupsFilter.d.ts","sourceRoot":"","sources":["../../../../../src/components/case-list/case-list-filters/GroupsFilter.tsx"],"names":[],"mappings":"AAmBA,OAAO,KAA2D,MAAM,OAAO,CAAC;AAShF,wBAAgB,YAAY,sBA2P3B"}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Button, Divider, MenuToggle, Select, SelectList, SelectOption, TextInputGroup, TextInputGroupMain, TextInputGroupUtilities, } from '@patternfly/react-core';
|
|
2
|
+
import TimesIcon from '@patternfly/react-icons/dist/js/icons/times-icon';
|
|
2
3
|
import { GlobalMetadataStateContext } from '@rh-support/react-context';
|
|
3
4
|
import { ability, resourceActions, resources } from '@rh-support/user-permissions';
|
|
4
|
-
import { getDropdownBtnPlaceholder
|
|
5
|
-
import
|
|
5
|
+
import { getDropdownBtnPlaceholder } from '@rh-support/utils';
|
|
6
|
+
import isEmpty from 'lodash/isEmpty';
|
|
7
|
+
import isUndefined from 'lodash/isUndefined';
|
|
8
|
+
import React, { useContext, useEffect, useMemo, useRef, useState } from 'react';
|
|
6
9
|
import { Trans, useTranslation } from 'react-i18next';
|
|
7
10
|
import { Link } from 'react-router-dom';
|
|
8
|
-
import { FILTER_SEARCHABLE_MODE_LIMIT } from '../../../enums/caseSearch';
|
|
9
11
|
import { SolrKeys } from '../../../enums/filters';
|
|
10
12
|
import { filterNamesMap } from '../../../utils/constants';
|
|
11
13
|
import { CaseListFilterDispatchContext, CaseListFilterStateContext } from '../CaseListFilterContext';
|
|
@@ -15,30 +17,157 @@ export function GroupsFilter() {
|
|
|
15
17
|
const { globalMetadataState: { caseGroups }, } = useContext(GlobalMetadataStateContext);
|
|
16
18
|
const { filterInfo } = useContext(CaseListFilterStateContext);
|
|
17
19
|
const dispatch = useContext(CaseListFilterDispatchContext);
|
|
20
|
+
const [inputValue, setInputValue] = useState('');
|
|
21
|
+
const [focusedItemIndex, setFocusedItemIndex] = useState(null);
|
|
22
|
+
const [activeItem, setActiveItem] = useState(null);
|
|
23
|
+
const list = [
|
|
24
|
+
...(caseGroups.data ? caseGroups === null || caseGroups === void 0 ? void 0 : caseGroups.data.map((group) => ({ value: group.name, key: group.groupNum })) : []),
|
|
25
|
+
];
|
|
26
|
+
const [selectOptions, setSelectOptions] = useState(list);
|
|
18
27
|
const canViewManageTab = ability.can(resourceActions.READ, resources.MANAGE);
|
|
19
28
|
const canViewCaseGroups = ability.can(resourceActions.READ, resources.CASE_GROUPS) && canViewManageTab;
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
29
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
30
|
+
const [selectedItems, setSelectedItems] = useState({});
|
|
31
|
+
const textInputRef = useRef();
|
|
32
|
+
const onToggleClick = () => {
|
|
33
|
+
setIsOpen(!isOpen);
|
|
23
34
|
};
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
})
|
|
35
|
+
const onSelect = (option) => {
|
|
36
|
+
const prevSelectedGroups = Object.keys(selectedItems).filter((item) => selectedItems[item] && item);
|
|
37
|
+
if (selectedItems[option.value]) {
|
|
38
|
+
setSelectedItems((prevData) => (Object.assign(Object.assign({}, prevData), { [option.value]: !prevData[option.value] })));
|
|
39
|
+
const indexOfGroup = prevSelectedGroups.indexOf(option.value);
|
|
40
|
+
prevSelectedGroups.splice(indexOfGroup, 1);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
setSelectedItems((prevData) => (Object.assign(Object.assign({}, prevData), { [option.value]: true })));
|
|
44
|
+
prevSelectedGroups.push(option.value);
|
|
45
|
+
}
|
|
46
|
+
const mapValueToKey = (value) => {
|
|
47
|
+
const selectedItem = list.find((item) => item.value === value);
|
|
48
|
+
return selectedItem;
|
|
49
|
+
};
|
|
50
|
+
const updatedFilterValues = prevSelectedGroups.map((item) => mapValueToKey(item));
|
|
51
|
+
updateFilter(dispatch, {
|
|
52
|
+
filterKey: SolrKeys.group,
|
|
53
|
+
values: updatedFilterValues,
|
|
54
|
+
});
|
|
55
|
+
};
|
|
56
|
+
const handleMenuArrowKeys = (key) => {
|
|
57
|
+
let indexToFocus;
|
|
58
|
+
if (isOpen) {
|
|
59
|
+
if (key === 'ArrowUp') {
|
|
60
|
+
// When no index is set or at the first index, focus to the last, otherwise decrement focus index
|
|
61
|
+
if (focusedItemIndex === null || focusedItemIndex === 0) {
|
|
62
|
+
indexToFocus = (list === null || list === void 0 ? void 0 : list.length) - 1;
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
indexToFocus = focusedItemIndex - 1;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (key === 'ArrowDown') {
|
|
69
|
+
// When no index is set or at the last index, focus to the first, otherwise increment focus index
|
|
70
|
+
if (focusedItemIndex === null || focusedItemIndex === (list === null || list === void 0 ? void 0 : list.length) - 1) {
|
|
71
|
+
indexToFocus = 0;
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
indexToFocus = focusedItemIndex + 1;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
setFocusedItemIndex(indexToFocus);
|
|
78
|
+
const focusedItem = list[indexToFocus];
|
|
79
|
+
setActiveItem(`select-multi-typeahead-checkbox-${focusedItem === null || focusedItem === void 0 ? void 0 : focusedItem.value.replace(' ', '-')}`);
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
const onInputKeyDown = (event) => {
|
|
83
|
+
const focusedItem = focusedItemIndex ? list[focusedItemIndex] : list[0];
|
|
84
|
+
switch (event.key) {
|
|
85
|
+
// Select the first available option
|
|
86
|
+
case 'Enter':
|
|
87
|
+
if (!isOpen) {
|
|
88
|
+
setIsOpen((prevIsOpen) => !prevIsOpen);
|
|
89
|
+
}
|
|
90
|
+
else if (isOpen && (focusedItem === null || focusedItem === void 0 ? void 0 : focusedItem.value) !== 'no results') {
|
|
91
|
+
onSelect(focusedItem === null || focusedItem === void 0 ? void 0 : focusedItem.value);
|
|
92
|
+
}
|
|
93
|
+
break;
|
|
94
|
+
case 'Tab':
|
|
95
|
+
case 'Escape':
|
|
96
|
+
setIsOpen(false);
|
|
97
|
+
setActiveItem(null);
|
|
98
|
+
break;
|
|
99
|
+
case 'ArrowUp':
|
|
100
|
+
case 'ArrowDown':
|
|
101
|
+
event.preventDefault();
|
|
102
|
+
handleMenuArrowKeys(event.key);
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
const onTextInputChange = (_event, value) => {
|
|
107
|
+
setInputValue(value);
|
|
108
|
+
};
|
|
109
|
+
const placeholder = getDropdownBtnPlaceholder(t('Select a group'), filterInfo[SolrKeys.group], '', (caseGroups.data || []).length, t('All selected'));
|
|
110
|
+
const onClick = () => {
|
|
111
|
+
var _a;
|
|
112
|
+
setInputValue('');
|
|
113
|
+
setSelectedItems({});
|
|
114
|
+
updateFilter(dispatch, {
|
|
115
|
+
filterKey: SolrKeys.group,
|
|
116
|
+
values: [],
|
|
117
|
+
});
|
|
118
|
+
(_a = textInputRef === null || textInputRef === void 0 ? void 0 : textInputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
119
|
+
};
|
|
120
|
+
const toggle = (toggleRef) => (React.createElement(MenuToggle, { variant: "typeahead", onClick: onToggleClick, innerRef: toggleRef, isExpanded: isOpen, isFullWidth: true },
|
|
121
|
+
React.createElement(TextInputGroup, { isPlain: true },
|
|
122
|
+
React.createElement(TextInputGroupMain, Object.assign({ value: inputValue, onClick: onToggleClick, onChange: onTextInputChange, onKeyDown: onInputKeyDown, id: "multi-typeahead-select-checkbox-input", autoComplete: "off", innerRef: textInputRef, placeholder: placeholder }, (activeItem && { 'aria-activedescendant': activeItem }), { role: "combobox", isExpanded: isOpen, "aria-controls": "select-multi-typeahead-checkbox-listbox" })),
|
|
123
|
+
Object.keys(selectedItems).filter((key) => selectedItems[key] === true).length ? (React.createElement(TextInputGroupUtilities, null,
|
|
124
|
+
React.createElement(Button, { variant: "plain", onClick: onClick, "aria-label": "Clear input value" },
|
|
125
|
+
React.createElement(TimesIcon, { "aria-hidden": true })))) : (''))));
|
|
126
|
+
const dropdownOptions = useMemo(() => {
|
|
127
|
+
return (!isEmpty(selectOptions) ? selectOptions : list).map((option, index) => !isUndefined(option.value) && (React.createElement(SelectOption, { key: option.key, value: option, hasCheckbox: true, isSelected: selectedItems[option.value], isFocused: focusedItemIndex !== null && focusedItemIndex === index, id: `select-multi-typeahead-${option.value.replace(' ', '-')}` }, option.value)));
|
|
128
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
129
|
+
}, [selectedItems, caseGroups === null || caseGroups === void 0 ? void 0 : caseGroups.data, selectOptions, focusedItemIndex]);
|
|
130
|
+
useEffect(() => {
|
|
131
|
+
let newSelectOptions = list;
|
|
132
|
+
// Filter menu items based on the text input value when one exists
|
|
133
|
+
if (inputValue) {
|
|
134
|
+
newSelectOptions = list.filter((option) => String(option === null || option === void 0 ? void 0 : option.value).toLowerCase().startsWith(inputValue.toLowerCase()));
|
|
135
|
+
// When no options are found after filtering, display 'No results found'
|
|
136
|
+
if (!newSelectOptions.length) {
|
|
137
|
+
newSelectOptions = [{ isDisabled: false, children: `No results found` }];
|
|
138
|
+
}
|
|
139
|
+
// Open the menu when the input value changes and the new value is not empty
|
|
140
|
+
if (!isOpen) {
|
|
141
|
+
setIsOpen(true);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
setSelectOptions(newSelectOptions);
|
|
145
|
+
setFocusedItemIndex(null);
|
|
146
|
+
setActiveItem(null);
|
|
147
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
148
|
+
}, [inputValue]);
|
|
149
|
+
useEffect(() => {
|
|
150
|
+
var _a;
|
|
151
|
+
if (isEmpty(filterInfo[SolrKeys.group])) {
|
|
152
|
+
setSelectedItems({});
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
const selectedGroups = (_a = filterInfo[SolrKeys.group]) === null || _a === void 0 ? void 0 : _a.reduce((selection, group) => {
|
|
156
|
+
selection[group === null || group === void 0 ? void 0 : group.value] = true;
|
|
157
|
+
return selection;
|
|
158
|
+
}, {});
|
|
159
|
+
setSelectedItems(selectedGroups);
|
|
160
|
+
}
|
|
161
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
162
|
+
}, [filterInfo[SolrKeys.group]]);
|
|
163
|
+
return (React.createElement("div", { className: "group-filter" },
|
|
164
|
+
React.createElement("label", { htmlFor: "case-list-group-filter", className: "pf-v5-u-mb-sm group-filter-label" }, t(filterNamesMap[SolrKeys.group])),
|
|
165
|
+
React.createElement("div", { className: "pf-v5-c-select" },
|
|
166
|
+
React.createElement(Select, { role: "menu", "data-tracking-id": "groups-filter", id: "case-list-group-filter", title: t(filterNamesMap[SolrKeys.group]), isOpen: isOpen, selected: selectedItems, onSelect: (_e, v) => onSelect(v), onOpenChange: (nextOpen) => setIsOpen(nextOpen), popperProps: { direction: 'down', enableFlip: false }, toggle: toggle, isScrollable: true },
|
|
167
|
+
React.createElement(SelectList, null, dropdownOptions),
|
|
168
|
+
canViewCaseGroups && (React.createElement(React.Fragment, null,
|
|
169
|
+
React.createElement(Divider, null),
|
|
170
|
+
React.createElement(SelectList, null,
|
|
171
|
+
React.createElement(Link, { className: "cta cta-link pf-v5-c-select__menu-item", to: "/manage/groups" },
|
|
172
|
+
React.createElement(Trans, null, "Manage groups")))))))));
|
|
44
173
|
}
|
|
@@ -9,9 +9,28 @@
|
|
|
9
9
|
.pf-v5-c-select__menu {
|
|
10
10
|
z-index: 1;
|
|
11
11
|
}
|
|
12
|
+
li.pf-v5-c-menu__list-item {
|
|
13
|
+
font-size: 16px;
|
|
14
|
+
font-weight: 400;
|
|
15
|
+
}
|
|
12
16
|
}
|
|
13
17
|
|
|
14
18
|
.pf-v5-c-menu__group-title {
|
|
15
19
|
margin: 0;
|
|
16
20
|
padding: 0;
|
|
17
21
|
}
|
|
22
|
+
|
|
23
|
+
label.pf-v5-u-mb-sm.group-filter-label,
|
|
24
|
+
.case-list-account-filter-label,
|
|
25
|
+
.case-list-username-filter-label {
|
|
26
|
+
font-size: 14px !important;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.group-filter {
|
|
30
|
+
span.pf-v5-c-menu-toggle__text {
|
|
31
|
+
color: var(--pf-v5-global--palette--black-600);
|
|
32
|
+
}
|
|
33
|
+
#case-list-group-filter {
|
|
34
|
+
z-index: 9 !important;
|
|
35
|
+
}
|
|
36
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rh-support/cases",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.70",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public",
|
|
6
6
|
"registry": "https://registry.npmjs.org"
|
|
@@ -43,8 +43,8 @@
|
|
|
43
43
|
"@patternfly/patternfly": "5.1.0",
|
|
44
44
|
"@patternfly/react-core": "5.1.1",
|
|
45
45
|
"@patternfly/react-table": "5.1.1",
|
|
46
|
-
"@rh-support/components": "2.1.
|
|
47
|
-
"@rh-support/react-context": "2.1.
|
|
46
|
+
"@rh-support/components": "2.1.54",
|
|
47
|
+
"@rh-support/react-context": "2.1.60",
|
|
48
48
|
"@rh-support/types": "2.0.3",
|
|
49
49
|
"@rh-support/user-permissions": "2.1.39",
|
|
50
50
|
"@rh-support/utils": "2.1.29",
|
|
@@ -96,5 +96,5 @@
|
|
|
96
96
|
"defaults and supports es6-module",
|
|
97
97
|
"maintained node versions"
|
|
98
98
|
],
|
|
99
|
-
"gitHead": "
|
|
99
|
+
"gitHead": "acb84e1dd7cb6d68a81c0a0871e5a203b6d7a67b"
|
|
100
100
|
}
|