@rh-support/manage 2.6.1 → 2.6.10

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.
Files changed (157) hide show
  1. package/lib/esm/ManageTabs.d.ts.map +1 -1
  2. package/lib/esm/ManageTabs.js +48 -20
  3. package/lib/esm/Routes.d.ts +1 -0
  4. package/lib/esm/Routes.d.ts.map +1 -1
  5. package/lib/esm/Routes.js +6 -0
  6. package/lib/esm/components/Configs/ConfigsTable.d.ts.map +1 -1
  7. package/lib/esm/components/Configs/ConfigsTable.js +33 -9
  8. package/lib/esm/components/Groups/AddMembersModal/AddMembersModal.d.ts +12 -0
  9. package/lib/esm/components/Groups/AddMembersModal/AddMembersModal.d.ts.map +1 -0
  10. package/lib/esm/components/Groups/AddMembersModal/AddMembersModal.js +80 -0
  11. package/lib/esm/components/Groups/AddMembersModal/index.d.ts +2 -0
  12. package/lib/esm/components/Groups/AddMembersModal/index.d.ts.map +1 -0
  13. package/lib/esm/components/Groups/AddMembersModal/index.js +1 -0
  14. package/lib/esm/components/Groups/DefualtGroupSwitch/DefaultGroupSwitch.d.ts +5 -3
  15. package/lib/esm/components/Groups/DefualtGroupSwitch/DefaultGroupSwitch.d.ts.map +1 -1
  16. package/lib/esm/components/Groups/DefualtGroupSwitch/DefaultGroupSwitch.js +21 -14
  17. package/lib/esm/components/Groups/GroupSelect/GroupSelect.d.ts +1 -0
  18. package/lib/esm/components/Groups/GroupSelect/GroupSelect.d.ts.map +1 -1
  19. package/lib/esm/components/Groups/GroupSelect/GroupSelect.js +240 -105
  20. package/lib/esm/components/Groups/GroupUserPermissionsSelect/GroupUserPermissionsSelect.d.ts.map +1 -1
  21. package/lib/esm/components/Groups/GroupUserPermissionsSelect/GroupUserPermissionsSelect.js +19 -14
  22. package/lib/esm/components/Groups/ManageGroupUsers/ManageGroupUsers.d.ts.map +1 -1
  23. package/lib/esm/components/Groups/ManageGroupUsers/ManageGroupUsers.js +187 -77
  24. package/lib/esm/components/ManageBookmarkedAccountsTab/AddEditBookmarkModal.d.ts.map +1 -1
  25. package/lib/esm/components/ManageBookmarkedAccountsTab/AddEditBookmarkModal.js +15 -12
  26. package/lib/esm/components/ManageBookmarkedAccountsTab/BookmarkAccountSelector.d.ts.map +1 -1
  27. package/lib/esm/components/ManageBookmarkedAccountsTab/BookmarkAccountSelector.js +106 -67
  28. package/lib/esm/components/ManageBookmarkedAccountsTab/BookmarkGroupSelector.d.ts.map +1 -1
  29. package/lib/esm/components/ManageBookmarkedAccountsTab/ManageGroupedBookmarkedAccountsTab.d.ts.map +1 -1
  30. package/lib/esm/components/ManageBookmarkedAccountsTab/ManageGroupedBookmarkedAccountsTab.js +15 -22
  31. package/lib/esm/components/ManageCaseLabels/AddEditCaseLabelModal.d.ts +19 -0
  32. package/lib/esm/components/ManageCaseLabels/AddEditCaseLabelModal.d.ts.map +1 -0
  33. package/lib/esm/components/ManageCaseLabels/AddEditCaseLabelModal.js +97 -0
  34. package/lib/esm/components/ManageCaseLabels/ManageCaseLabelsTab.d.ts +3 -0
  35. package/lib/esm/components/ManageCaseLabels/ManageCaseLabelsTab.d.ts.map +1 -0
  36. package/lib/esm/components/ManageCaseLabels/ManageCaseLabelsTab.js +220 -0
  37. package/lib/esm/components/ManageCaseLabels/index.d.ts +2 -0
  38. package/lib/esm/components/ManageCaseLabels/index.d.ts.map +1 -0
  39. package/lib/esm/components/ManageCaseLabels/index.js +1 -0
  40. package/lib/esm/components/ManageCaseLabels/types.d.ts +6 -0
  41. package/lib/esm/components/ManageCaseLabels/types.d.ts.map +1 -0
  42. package/lib/esm/components/ManageCaseLabels/types.js +1 -0
  43. package/lib/esm/components/ManageExpiredContents/ExpiredContentCategory.js +4 -4
  44. package/lib/esm/components/ManageExpiredContents/ExpiredContentHeader.js +1 -1
  45. package/lib/esm/components/ManageExpiredContents/ExpiredContentManager.d.ts.map +1 -1
  46. package/lib/esm/components/ManageExpiredContents/ExpiredContentManager.js +12 -12
  47. package/lib/esm/components/ManageExpiredContents/ExpiredContentSingleItem.js +3 -3
  48. package/lib/esm/components/ManageExpiredContents/ExpiredContentSingleItemView.d.ts.map +1 -1
  49. package/lib/esm/components/ManageExpiredContents/ExpiredContentSingleItemView.js +43 -35
  50. package/lib/esm/components/ManagePartnerships/NonOrgCustomerInfoModal.d.ts.map +1 -1
  51. package/lib/esm/components/ManagePartnerships/NonOrgCustomerInfoModal.js +8 -5
  52. package/lib/esm/components/ManagePartnerships/PartnershipsList.d.ts.map +1 -1
  53. package/lib/esm/components/ManagePartnerships/PartnershipsList.js +19 -12
  54. package/lib/esm/components/ManagePartnerships/PartnershipsTermsModal.d.ts.map +1 -1
  55. package/lib/esm/components/ManagePartnerships/PartnershipsTermsModal.js +17 -20
  56. package/lib/esm/components/ManagePartnerships/RequestCollaborationModal.d.ts.map +1 -1
  57. package/lib/esm/components/ManagePartnerships/RequestCollaborationModal.js +39 -27
  58. package/lib/esm/components/ManagePartnerships/Requests.d.ts +1 -0
  59. package/lib/esm/components/ManagePartnerships/Requests.d.ts.map +1 -1
  60. package/lib/esm/components/ManagePartnerships/Requests.js +22 -9
  61. package/lib/esm/components/ManagePartnerships/index.js +1 -1
  62. package/lib/esm/components/ManagePreferences/PreferencesBody.d.ts.map +1 -1
  63. package/lib/esm/components/ManagePreferences/PreferencesBody.js +1 -5
  64. package/lib/esm/components/ManagePreferences/PreferencesHeader.js +1 -1
  65. package/lib/esm/components/ManagePreferences/components/PreferenceSelect.d.ts +1 -1
  66. package/lib/esm/components/ManagePreferences/components/PreferenceSelect.d.ts.map +1 -1
  67. package/lib/esm/components/ManagePreferences/components/PreferenceSelect.js +26 -27
  68. package/lib/esm/components/ManagePreferences/components/PreferenceSwitch.d.ts.map +1 -1
  69. package/lib/esm/components/ManagePreferences/components/PreferenceSwitch.js +6 -6
  70. package/lib/esm/components/ManagePreferences/sections/PreferencesACL.d.ts.map +1 -1
  71. package/lib/esm/components/ManagePreferences/sections/PreferencesACL.js +8 -9
  72. package/lib/esm/components/ManagePreferences/sections/PreferencesCaseCreate.d.ts.map +1 -1
  73. package/lib/esm/components/ManagePreferences/sections/PreferencesCaseCreate.js +77 -63
  74. package/lib/esm/components/ManagePreferences/sections/PreferencesCaseSearch.d.ts.map +1 -1
  75. package/lib/esm/components/ManagePreferences/sections/PreferencesCaseSearch.js +3 -4
  76. package/lib/esm/components/ManagePreferences/sections/PreferencesCaseView.d.ts.map +1 -1
  77. package/lib/esm/components/ManagePreferences/sections/PreferencesCaseView.js +47 -103
  78. package/lib/esm/components/ManageTable/ManageTable.d.ts +3 -4
  79. package/lib/esm/components/ManageTable/ManageTable.d.ts.map +1 -1
  80. package/lib/esm/components/ManageTable/ManageTable.js +12 -18
  81. package/lib/esm/components/ManageTags/TagsManager.d.ts.map +1 -1
  82. package/lib/esm/components/ManageTags/TagsManager.js +58 -50
  83. package/lib/esm/components/NotificationEmails/NotificationEmailsModal.d.ts.map +1 -1
  84. package/lib/esm/components/NotificationEmails/NotificationEmailsModal.js +35 -26
  85. package/lib/esm/components/NotificationEmails/index.d.ts.map +1 -1
  86. package/lib/esm/components/NotificationEmails/index.js +10 -7
  87. package/lib/esm/components/TopContentManagement/CategoryLimit/CategoryLimit.d.ts.map +1 -1
  88. package/lib/esm/components/TopContentManagement/CategoryLimit/CategoryLimit.js +2 -3
  89. package/lib/esm/components/TopContentManagement/CategoryLimit/CategoryLimitGuidelines.js +6 -6
  90. package/lib/esm/components/TopContentManagement/CategoryLimit/QuestionAnswer.js +1 -1
  91. package/lib/esm/components/TopContentManagement/ContentUsage/ContentAccordion.d.ts.map +1 -1
  92. package/lib/esm/components/TopContentManagement/ContentUsage/ContentAccordion.js +7 -9
  93. package/lib/esm/components/TopContentManagement/ContentUsage/PerformanceMetricClickCount.d.ts +1 -0
  94. package/lib/esm/components/TopContentManagement/ContentUsage/PerformanceMetricClickCount.d.ts.map +1 -1
  95. package/lib/esm/components/TopContentManagement/ContentUsage/PerformanceMetricClickCount.js +2 -2
  96. package/lib/esm/components/TopContentManagement/ContentUsage/PerformanceMetrics.d.ts.map +1 -1
  97. package/lib/esm/components/TopContentManagement/ContentUsage/PerformanceMetrics.js +12 -10
  98. package/lib/esm/components/TopContentManagement/ContentUsage/PerformanceMetricsSelect.d.ts +2 -3
  99. package/lib/esm/components/TopContentManagement/ContentUsage/PerformanceMetricsSelect.d.ts.map +1 -1
  100. package/lib/esm/components/TopContentManagement/ContentUsage/PerformanceMetricsSelect.js +16 -9
  101. package/lib/esm/components/TopContentManagement/ContentUsage/VersionPerformanceMetrics.d.ts.map +1 -1
  102. package/lib/esm/components/TopContentManagement/ContentUsage/VersionPerformanceMetrics.js +15 -16
  103. package/lib/esm/components/TopContentManagement/NoTopContentFound.d.ts.map +1 -1
  104. package/lib/esm/components/TopContentManagement/NoTopContentFound.js +14 -15
  105. package/lib/esm/components/TopContentManagement/TopContentEditor/TopContentCategoryContent/AddNewCategoryDropDown.d.ts.map +1 -1
  106. package/lib/esm/components/TopContentManagement/TopContentEditor/TopContentCategoryContent/AddNewCategoryDropDown.js +47 -39
  107. package/lib/esm/components/TopContentManagement/TopContentEditor/TopContentCategoryContent/TopContentCategory.d.ts.map +1 -1
  108. package/lib/esm/components/TopContentManagement/TopContentEditor/TopContentCategoryContent/TopContentCategory.js +12 -6
  109. package/lib/esm/components/TopContentManagement/TopContentEditor/TopContentCategoryContent/TopContentCategoryNew.js +3 -3
  110. package/lib/esm/components/TopContentManagement/TopContentEditor/TopContentCategoryContent/TopContentComponent.d.ts.map +1 -1
  111. package/lib/esm/components/TopContentManagement/TopContentEditor/TopContentCategoryContent/TopContentComponent.js +11 -7
  112. package/lib/esm/components/TopContentManagement/TopContentEditor/TopContentCategoryContent/TopContentSingleItem.d.ts.map +1 -1
  113. package/lib/esm/components/TopContentManagement/TopContentEditor/TopContentCategoryContent/TopContentSingleItem.js +62 -53
  114. package/lib/esm/components/TopContentManagement/TopContentEditor/TopContentCategoryContent/TopContentSingleItemLink.d.ts.map +1 -1
  115. package/lib/esm/components/TopContentManagement/TopContentEditor/TopContentCategoryContent/TopContentSingleItemLink.js +2 -3
  116. package/lib/esm/components/TopContentManagement/TopContentEditor/TopContentEditor.d.ts.map +1 -1
  117. package/lib/esm/components/TopContentManagement/TopContentEditor/TopContentEditor.js +8 -9
  118. package/lib/esm/components/TopContentManagement/TopContentEditor/TopContentSuggestion/TopContentSuggestion.js +2 -2
  119. package/lib/esm/components/TopContentManagement/TopContentEditor/TopContentSuggestion/TopContentSuggestionHint.js +4 -5
  120. package/lib/esm/components/TopContentManagement/TopContentEditor/TopContentSuggestion/TopContentSuggestionHintAccept.d.ts.map +1 -1
  121. package/lib/esm/components/TopContentManagement/TopContentEditor/TopContentSuggestion/TopContentSuggestionHintAccept.js +51 -25
  122. package/lib/esm/components/TopContentManagement/TopContentHeader.js +1 -1
  123. package/lib/esm/components/TopContentManagement/TopContentProductVersionSelector.d.ts.map +1 -1
  124. package/lib/esm/components/TopContentManagement/TopContentProductVersionSelector.js +64 -32
  125. package/lib/esm/constants/GroupSelectActions.d.ts +2 -1
  126. package/lib/esm/constants/GroupSelectActions.d.ts.map +1 -1
  127. package/lib/esm/constants/GroupSelectActions.js +1 -0
  128. package/lib/esm/constants/PartnershipLink.d.ts +3 -0
  129. package/lib/esm/constants/PartnershipLink.d.ts.map +1 -0
  130. package/lib/esm/constants/PartnershipLink.js +2 -0
  131. package/lib/esm/context/ExpiredContentContextProvider.d.ts.map +1 -1
  132. package/lib/esm/hooks/useCaseGroupGraphQL.d.ts +42 -0
  133. package/lib/esm/hooks/useCaseGroupGraphQL.d.ts.map +1 -0
  134. package/lib/esm/hooks/useCaseGroupGraphQL.js +117 -0
  135. package/lib/esm/hooks/useCaseLabelGraphQL.d.ts +26 -0
  136. package/lib/esm/hooks/useCaseLabelGraphQL.d.ts.map +1 -0
  137. package/lib/esm/hooks/useCaseLabelGraphQL.js +104 -0
  138. package/lib/esm/hooks/useCurrentUserContact.d.ts +8 -0
  139. package/lib/esm/hooks/useCurrentUserContact.d.ts.map +1 -0
  140. package/lib/esm/hooks/useCurrentUserContact.js +74 -0
  141. package/lib/esm/hooks/useVersionsDiffer.d.ts.map +1 -1
  142. package/lib/esm/index.d.ts.map +1 -1
  143. package/lib/esm/index.js +2 -0
  144. package/lib/esm/reducers/ExpiredContentReducer.d.ts.map +1 -1
  145. package/lib/esm/reducers/ManagePartnershipsReducer.d.ts.map +1 -1
  146. package/lib/esm/reducers/TagManagmentReducer.d.ts +1 -1
  147. package/lib/esm/reducers/TagManagmentReducer.d.ts.map +1 -1
  148. package/lib/esm/reducers/TopContentHelpers.d.ts.map +1 -1
  149. package/lib/esm/reducers/TopContentReducer.d.ts.map +1 -1
  150. package/lib/esm/reducers/TopContentReducer.js +5 -2
  151. package/lib/esm/scss/_main.scss +266 -24
  152. package/lib/esm/scss/_pf-overrides.scss +66 -53
  153. package/lib/esm/scss/index.scss +5 -4
  154. package/lib/esm/utils/caseGroupMapper.d.ts +18 -0
  155. package/lib/esm/utils/caseGroupMapper.d.ts.map +1 -0
  156. package/lib/esm/utils/caseGroupMapper.js +50 -0
  157. package/package.json +21 -22
@@ -7,39 +7,95 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
- import { publicApi } from '@cee-eng/hydrajs';
11
- import { SearchInput } from '@patternfly/react-core';
12
- import { AlertMessage, AlertType, ErrorBoundary, ToastNotification, useFetch, usePrevious, } from '@rh-support/components';
13
- import { useGlobalStateContext } from '@rh-support/react-context';
10
+ import { Button, Modal, ModalBody, ModalFooter, ModalHeader, ModalVariant, SearchInput, Tooltip, } from '@patternfly/react-core';
11
+ import { ErrorBoundary, ToastNotification, usePrevious } from '@rh-support/components';
12
+ import { GlobalMetadataReducerConstants, useGlobalDispatchContext, useGlobalStateContext, } from '@rh-support/react-context';
13
+ import { ability, resourceActions, resources } from '@rh-support/user-permissions';
14
14
  import isEmpty from 'lodash/isEmpty';
15
15
  import React, { useEffect, useMemo, useState } from 'react';
16
16
  import { Trans, useTranslation } from 'react-i18next';
17
- import { Link, useLocation } from 'react-router-dom';
17
+ import { useLocation } from 'react-router-dom';
18
+ import { useCaseGroupMembers, useDeleteCaseGroupMember, useToggleDefaultGroup, } from '../../../hooks/useCaseGroupGraphQL';
18
19
  import { ManageTable } from '../../ManageTable/ManageTable';
20
+ import { AddMembersModal } from '../AddMembersModal';
19
21
  import { DefaultGroupSwitch } from '../DefualtGroupSwitch';
20
22
  import { GroupSelect } from '../GroupSelect';
21
- import { GroupUserPermissionsSelect } from '../GroupUserPermissionsSelect';
23
+ // TODO: Uncomment when updateUsers is migrated to GraphQL
24
+ // import { GroupUserPermissionsSelect } from '../GroupUserPermissionsSelect';
25
+ const RemoveMemberButton = ({ user, onRemove, isDisabled }) => {
26
+ const { t } = useTranslation();
27
+ const button = (React.createElement(Button, { variant: "link", isDanger: true, onClick: () => onRemove(user), isAriaDisabled: user.isOrgAdmin || isDisabled }, t('Remove')));
28
+ if (user.isOrgAdmin) {
29
+ return (React.createElement(Tooltip, { content: t('Organization Administrators cannot be removed because they have access to all groups') }, button));
30
+ }
31
+ return button;
32
+ };
22
33
  export const ManageGroupUsers = () => {
34
+ var _a, _b;
23
35
  const { t } = useTranslation();
24
36
  const location = useLocation();
25
- const { globalMetadataState: { loggedInUsersAccount, loggedInUserRights }, } = useGlobalStateContext();
37
+ const { globalMetadataState: { caseGroups, loggedInUsersAccount, loggedInUser }, } = useGlobalStateContext();
38
+ const dispatchToGlobalMetadataReducer = useGlobalDispatchContext();
26
39
  const disableGroupSelect = !loggedInUsersAccount || !loggedInUsersAccount.data || !loggedInUsersAccount.data.accountNumber;
27
40
  const [selectedGroup, setSelectedGroup] = useState();
28
- const { clearResponse, isFetching, request, data: response, } = useFetch(publicApi.caseGroups.getCaseGroupUsers);
29
- const groupUsers = useMemo(() => response || [], [response]);
30
- // errors
31
- function onPermissionError(error, user) {
32
- setData([...data]);
33
- const message = t(`Could not change permission for {{user}}: {{error}}`, {
34
- user: `${user.firstName} ${user.lastName}`,
35
- error: error.message,
36
- });
37
- ToastNotification.addDangerMessage(message);
38
- }
41
+ const { data: groupUsers, loading: isFetching, error: membersError, fetchMembers, refetch } = useCaseGroupMembers();
42
+ const previousMembersError = usePrevious(membersError);
43
+ useEffect(() => {
44
+ if (membersError && !previousMembersError) {
45
+ ToastNotification.addDangerMessage(t('There was an error loading group members. Please try again or refresh'));
46
+ }
47
+ }, [membersError, previousMembersError, t]);
48
+ const defaultCaseGroupId = (_b = (_a = loggedInUser === null || loggedInUser === void 0 ? void 0 : loggedInUser.data) === null || _a === void 0 ? void 0 : _a.defaultCaseGroup) !== null && _b !== void 0 ? _b : null;
49
+ const membersWithOrgAdmin = useMemo(() => {
50
+ var _a, _b, _c, _d;
51
+ const loggedInContact = loggedInUser === null || loggedInUser === void 0 ? void 0 : loggedInUser.data;
52
+ const selectedGroupId = selectedGroup === null || selectedGroup === void 0 ? void 0 : selectedGroup.groupNum;
53
+ const syncLoggedInUserDefault = (members) => {
54
+ if (!(loggedInContact === null || loggedInContact === void 0 ? void 0 : loggedInContact.ssoUsername) || !selectedGroupId)
55
+ return members;
56
+ return members.map((member) => member.ssoUsername === loggedInContact.ssoUsername
57
+ ? Object.assign(Object.assign({}, member), { isDefault: defaultCaseGroupId === selectedGroupId }) : member);
58
+ };
59
+ const members = syncLoggedInUserDefault(groupUsers || []);
60
+ const user = loggedInContact;
61
+ if (!(user === null || user === void 0 ? void 0 : user.isOrgAdmin) || !user.ssoUsername || !selectedGroup)
62
+ return members;
63
+ const alreadyPresent = members.some((m) => m.ssoUsername === user.ssoUsername);
64
+ if (alreadyPresent)
65
+ return members;
66
+ const syntheticEntry = {
67
+ firstName: (_a = user.firstName) !== null && _a !== void 0 ? _a : '',
68
+ lastName: (_b = user.lastName) !== null && _b !== void 0 ? _b : '',
69
+ isOrgAdmin: true,
70
+ access: true,
71
+ write: false,
72
+ isDefault: defaultCaseGroupId === selectedGroup.groupNum,
73
+ ssoUsername: user.ssoUsername,
74
+ email: (_c = user.email) !== null && _c !== void 0 ? _c : '',
75
+ contactSfId: (_d = user.id) !== null && _d !== void 0 ? _d : '',
76
+ memberRecordId: '',
77
+ };
78
+ return [...members, syntheticEntry];
79
+ }, [groupUsers, loggedInUser === null || loggedInUser === void 0 ? void 0 : loggedInUser.data, selectedGroup, defaultCaseGroupId]);
80
+ const canManageCaseGroups = ability.can(resourceActions.CREATE, resources.CASE_GROUPS);
81
+ const [isAddMembersModalOpen, setIsAddMembersModalOpen] = useState(false);
82
+ const [memberToRemove, setMemberToRemove] = useState(null);
83
+ const { deleteMember, loading: isDeleting } = useDeleteCaseGroupMember();
84
+ const { toggleDefault, loading: isClearingDefault } = useToggleDefaultGroup();
85
+ const isRemovingMember = isDeleting || isClearingDefault;
86
+ // TODO: Uncomment when updateUsers is migrated to GraphQL
87
+ // function onPermissionError(error: Error, user: IGroupUser) {
88
+ // setData([...data]);
89
+ // const message = t(`Could not change permission for {{user}}: {{error}}`, {
90
+ // user: `${user.firstName} ${user.lastName}`,
91
+ // error: error.message,
92
+ // });
93
+ // ToastNotification.addDangerMessage(message);
94
+ // }
39
95
  // set and sort fetched data.
40
- const [initialData, setInitialData] = useState(groupUsers);
41
- const [data, setData] = useState(groupUsers);
42
- useEffect(() => setAllData(response || []), [response]);
96
+ const [initialData, setInitialData] = useState(membersWithOrgAdmin);
97
+ const [data, setData] = useState(membersWithOrgAdmin);
98
+ useEffect(() => setAllData(membersWithOrgAdmin || []), [membersWithOrgAdmin]);
43
99
  function setAllData(users) {
44
100
  setInitialData(users);
45
101
  setData(users);
@@ -58,21 +114,74 @@ export const ManageGroupUsers = () => {
58
114
  return tempUser;
59
115
  }));
60
116
  };
117
+ const onDefaultToggleSuccess = (user, isChecked) => {
118
+ var _a;
119
+ if (user.ssoUsername !== ((_a = loggedInUser === null || loggedInUser === void 0 ? void 0 : loggedInUser.data) === null || _a === void 0 ? void 0 : _a.ssoUsername) || !selectedGroup)
120
+ return;
121
+ const groupId = isChecked ? selectedGroup.groupNum : null;
122
+ const updatedLoggedInUserData = Object.assign(Object.assign({}, loggedInUser.data), { defaultCaseGroup: groupId });
123
+ dispatchToGlobalMetadataReducer({
124
+ type: GlobalMetadataReducerConstants.setLoggedInUser,
125
+ payload: {
126
+ loggedInUser: Object.assign(Object.assign({}, loggedInUser), { data: updatedLoggedInUserData }),
127
+ },
128
+ });
129
+ if (caseGroups === null || caseGroups === void 0 ? void 0 : caseGroups.data) {
130
+ const updatedGroups = caseGroups.data.map((group) => (Object.assign(Object.assign({}, group), { isDefault: groupId !== null && group.groupNum === groupId })));
131
+ dispatchToGlobalMetadataReducer({
132
+ type: GlobalMetadataReducerConstants.setCaseGroups,
133
+ payload: {
134
+ caseGroups: Object.assign(Object.assign({}, caseGroups), { data: updatedGroups }),
135
+ },
136
+ });
137
+ }
138
+ };
61
139
  const onGroupSelect = (group) => __awaiter(void 0, void 0, void 0, function* () {
62
140
  setSelectedGroup(group);
63
141
  if (group) {
64
- request(loggedInUsersAccount.data.accountNumber, group.groupNum);
142
+ fetchMembers(group.groupNum);
65
143
  }
66
144
  else {
67
- clearResponse();
145
+ setAllData([]);
68
146
  }
69
147
  });
70
- function onPermissionsChange(user) {
71
- const initialUsers = initialData.map((value) => (value.ssoUsername === user.ssoUsername ? user : value));
72
- const users = data.map((value) => (value.ssoUsername === user.ssoUsername ? user : value));
73
- setInitialData(initialUsers);
74
- setData(users);
75
- }
148
+ const handleRemoveMember = () => __awaiter(void 0, void 0, void 0, function* () {
149
+ if (!(memberToRemove === null || memberToRemove === void 0 ? void 0 : memberToRemove.memberRecordId))
150
+ return;
151
+ const member = memberToRemove;
152
+ try {
153
+ if (member.isDefault) {
154
+ if (!member.contactSfId) {
155
+ ToastNotification.addDangerMessage(t('There was an error removing {{name}} from the group. Please try again or refresh.', {
156
+ name: `${member.firstName} ${member.lastName}`,
157
+ }));
158
+ return;
159
+ }
160
+ yield toggleDefault(member.contactSfId, null);
161
+ onDefaultToggleSuccess(member, false);
162
+ }
163
+ yield deleteMember(member.memberRecordId);
164
+ ToastNotification.addSuccessMessage(t('{{name}} has been removed from the group', {
165
+ name: `${member.firstName} ${member.lastName}`,
166
+ }));
167
+ refetch();
168
+ }
169
+ catch (error) {
170
+ ToastNotification.addDangerMessage(t('Could not remove member from group: {{message}}', {
171
+ message: error instanceof Error ? error.message : String(error),
172
+ }));
173
+ }
174
+ finally {
175
+ setMemberToRemove(null);
176
+ }
177
+ });
178
+ // TODO: Uncomment when updateUsers is migrated to GraphQL
179
+ // function onPermissionsChange(user: IGroupUser) {
180
+ // const initialUsers = initialData.map((value) => (value.ssoUsername === user.ssoUsername ? user : value));
181
+ // const users = data.map((value) => (value.ssoUsername === user.ssoUsername ? user : value));
182
+ // setInitialData(initialUsers);
183
+ // setData(users);
184
+ // }
76
185
  const columns = [
77
186
  {
78
187
  accessor: (user) => user.firstName,
@@ -92,16 +201,38 @@ export const ManageGroupUsers = () => {
92
201
  id: 'sso-username',
93
202
  title: t('Login'),
94
203
  },
95
- {
96
- id: 'permissions',
97
- title: t('Permissions'),
98
- cell: (user) => user.isOrgAdmin ? (t('Admin/Full access')) : (React.createElement(GroupUserPermissionsSelect, { onChange: onPermissionsChange, account: loggedInUsersAccount.data, group: selectedGroup, users: data, user: user, onError: onPermissionError })),
99
- },
100
- {
101
- id: 'default',
102
- title: t('Default group'),
103
- cell: (user, index) => (React.createElement(DefaultGroupSwitch, { id: `${index}`, onToggle: onDefaultToggle, group: selectedGroup, user: user })),
104
- },
204
+ // TODO: Uncomment when updateUsers is migrated to GraphQL
205
+ // {
206
+ // id: 'permissions',
207
+ // title: t('Permissions'),
208
+ // cell: (user) =>
209
+ // user.isOrgAdmin ? (
210
+ // t('Admin/Full access')
211
+ // ) : (
212
+ // <GroupUserPermissionsSelect
213
+ // onChange={onPermissionsChange}
214
+ // account={loggedInUsersAccount.data}
215
+ // group={selectedGroup}
216
+ // users={data}
217
+ // user={user}
218
+ // onError={onPermissionError}
219
+ // />
220
+ // ),
221
+ // },
222
+ ...(canManageCaseGroups
223
+ ? [
224
+ {
225
+ id: 'default',
226
+ title: t('Default group'),
227
+ cell: (user, index) => (React.createElement(DefaultGroupSwitch, { id: `${index}`, onToggle: onDefaultToggle, onToggleSuccess: onDefaultToggleSuccess, group: selectedGroup, user: user })),
228
+ },
229
+ {
230
+ id: 'remove',
231
+ title: '',
232
+ cell: (user) => (React.createElement(RemoveMemberButton, { user: user, onRemove: setMemberToRemove, isDisabled: isRemovingMember })),
233
+ },
234
+ ]
235
+ : []),
105
236
  ];
106
237
  // filter out search query.
107
238
  const [userSearch, setUserSearch] = useState('');
@@ -121,54 +252,33 @@ export const ManageGroupUsers = () => {
121
252
  else {
122
253
  setData(initialData);
123
254
  }
124
- }, [initialData, userSearch, setData, previousUserSearch, groupUsers]);
255
+ }, [initialData, userSearch, setData, previousUserSearch, membersWithOrgAdmin]);
125
256
  useEffect(() => {
126
257
  if (location.pathname !== '/manage/groups') {
127
258
  return;
128
259
  }
129
- setAllData(response || []);
260
+ setAllData(membersWithOrgAdmin || []);
130
261
  // eslint-disable-next-line react-hooks/exhaustive-deps
131
262
  }, [location.pathname, loggedInUsersAccount.data]);
132
263
  return (React.createElement(React.Fragment, null,
133
- React.createElement(AlertMessage, { variant: AlertType.INFO, show: loggedInUserRights.data.isOrgAdmin() &&
134
- !loggedInUsersAccount.data.hasGroupACLs &&
135
- !loggedInUserRights.data.isInternal(), isInline: true, className: "pf-v5-u-mb-md", title: t('Case Group ACL is not enabled') },
136
- React.createElement("p", null,
137
- React.createElement(Trans, { i18nKey: "i18nRequestControl" },
138
- "To use case groups to limit user access, enable the",
139
- ' ',
140
- React.createElement("a", { href: "https://access.redhat.com/articles/170453", target: "_blank", rel: "noopener noreferrer" }, "Case Group Access Control Lists (ACL)"),
141
- ' ',
142
- "under",
143
- ' ',
144
- React.createElement(Link, { key: "case-contact-phone-number-review", replace: true, to: {
145
- pathname: '/manage/preferences',
146
- }, "data-tracking-id": "case-contact-phone-number-review" }, "Preferences")),
147
- React.createElement("br", null),
148
- React.createElement(Trans, null, "You can organize and group related cases and filter on the case list page, but you cannot change permissions for case groups unless the Case Group ACL is enabled."))),
149
- React.createElement(AlertMessage, { variant: AlertType.INFO, show: loggedInUserRights.data.isInternal(), isInline: true, className: "pf-v5-u-mb-md", title: t('Case Group ACL is not available for internal users.') },
150
- React.createElement("p", null,
151
- React.createElement(Trans, { i18nKey: "i18nRequestControl" },
152
- "As an internal user you can use case group without ACL functionality. To use case groups to limit user access, customers can enable the",
153
- ' ',
154
- React.createElement("a", { href: "https://access.redhat.com/articles/170453", target: "_blank", rel: "noopener noreferrer" }, "Case Group Access Control Lists (ACL)"),
155
- ' ',
156
- "under",
157
- ' ',
158
- React.createElement(Link, { key: "case-contact-phone-number-review", replace: true, to: {
159
- pathname: '/manage/preferences',
160
- }, "data-tracking-id": "case-contact-phone-number-review" }, "Preferences")),
161
- React.createElement("br", null),
162
- React.createElement(Trans, null, "Customers can organize and group related cases and filter on the case list page, but they cannot change permissions for case groups unless the Case Group ACL is enabled."))),
163
264
  React.createElement("header", null,
164
- React.createElement("h2", null, t('Groups')),
165
- React.createElement("p", null, t('Add or edit groups to easily filter while searching through cases.'))),
166
- React.createElement("div", { className: "toolbar" },
167
- React.createElement(GroupSelect, { isDisabled: isFetching || disableGroupSelect, onSelect: onGroupSelect }),
265
+ React.createElement("h2", { className: "pf-v6-u-pb-sm" }, t('Groups')),
266
+ React.createElement("p", null, t('To filter cases while searching, add or edit groups.'))),
267
+ React.createElement("div", { className: "toolbar pf-v6-u-justify-content-space-between" },
268
+ React.createElement(GroupSelect, { isDisabled: isFetching || disableGroupSelect, onSelect: onGroupSelect, onAddMembers: () => setIsAddMembersModalOpen(true) }),
168
269
  React.createElement("span", { className: "toolbar-right" },
169
270
  React.createElement("label", { htmlFor: "account-group-filter" },
170
271
  React.createElement(Trans, null, "Filter by")),
171
- React.createElement(SearchInput, { className: "pf-v5-u-flex-grow-1 pf-v5-c-search-input pf-v5-u-background-color-100", id: "account-group-filter", value: userSearch, isDisabled: isFetching || !selectedGroup, onChange: (_, value) => setUserSearch(value), placeholder: t('Search for people in this group'), "aria-label": "Group search input", onClear: () => setUserSearch('') }))),
272
+ React.createElement(SearchInput, { className: "pf-v6-u-flex-grow-1 pf-v6-c-search-input pf-v6-u-background-color-100", id: "account-group-filter", value: userSearch, isDisabled: isFetching || !selectedGroup, onChange: (_, value) => setUserSearch(value), placeholder: t('Search for people in this group'), "aria-label": "Group search input", onClear: () => setUserSearch('') }))),
172
273
  React.createElement(ErrorBoundary, { errorMsgInfo: { message: t('There was an error loading group users list') } },
173
- React.createElement(ManageTable, { ariaLabel: t('Table to manage groups'), columns: columns, data: data, sortInfo: { column: 'first-name', direction: 'asc' }, isFetching: isFetching, isError: false }))));
274
+ React.createElement(ManageTable, { ariaLabel: t('Table to manage groups'), columns: columns, data: data, sortInfo: { column: 'first-name', direction: 'asc' }, isFetching: isFetching, isError: false, pagination: false })),
275
+ memberToRemove && (React.createElement(Modal, { variant: ModalVariant.small, isOpen: true, onClose: () => setMemberToRemove(null), "aria-label": t('Confirm removal') },
276
+ React.createElement(ModalHeader, { title: t('Remove member') }),
277
+ React.createElement(ModalBody, null, t('Are you sure you want to remove {{name}} from this group?', {
278
+ name: `${memberToRemove.firstName} ${memberToRemove.lastName}`,
279
+ })),
280
+ React.createElement(ModalFooter, null,
281
+ React.createElement(Button, { variant: "danger", onClick: handleRemoveMember, isLoading: isRemovingMember, isDisabled: isRemovingMember }, t('Remove')),
282
+ React.createElement(Button, { variant: "link", onClick: () => setMemberToRemove(null), isDisabled: isRemovingMember }, t('Cancel'))))),
283
+ canManageCaseGroups && isAddMembersModalOpen && selectedGroup && (React.createElement(AddMembersModal, { group: selectedGroup, existingMembers: initialData, onSuccess: refetch, onClose: () => setIsAddMembersModalOpen(false) }))));
174
284
  };
@@ -1 +1 @@
1
- {"version":3,"file":"AddEditBookmarkModal.d.ts","sourceRoot":"","sources":["../../../../src/components/ManageBookmarkedAccountsTab/AddEditBookmarkModal.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAGtD,OAAO,KAA8B,MAAM,OAAO,CAAC;AAMnD,UAAU,MAAM;IACZ,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,MAAM,EAAE,CAAC,gBAAgB,EAAE,SAAS,EAAE,EAAE,aAAa,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACxE,gBAAgB,EAAE,SAAS,EAAE,CAAC;IAC9B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,uBAAuB,EAAE,SAAS,EAAE,CAAC;IACrC,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,oBAAoB,UAAW,MAAM,sBA2IjD,CAAC"}
1
+ {"version":3,"file":"AddEditBookmarkModal.d.ts","sourceRoot":"","sources":["../../../../src/components/ManageBookmarkedAccountsTab/AddEditBookmarkModal.tsx"],"names":[],"mappings":"AASA,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAGtD,OAAO,KAA8B,MAAM,OAAO,CAAC;AAMnD,UAAU,MAAM;IACZ,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,MAAM,EAAE,CAAC,gBAAgB,EAAE,SAAS,EAAE,EAAE,aAAa,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACxE,gBAAgB,EAAE,SAAS,EAAE,CAAC;IAC9B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,uBAAuB,EAAE,SAAS,EAAE,CAAC;IACrC,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,oBAAoB,GAAI,OAAO,MAAM,sBA8IjD,CAAC"}
@@ -1,4 +1,4 @@
1
- import { Button, ButtonVariant, Modal, ModalVariant } from '@patternfly/react-core';
1
+ import { Button, ButtonVariant, Modal, ModalBody, ModalFooter, ModalHeader, ModalVariant, } from '@patternfly/react-core';
2
2
  import isEmpty from 'lodash/isEmpty';
3
3
  import isEqual from 'lodash/isEqual';
4
4
  import React, { useEffect, useState } from 'react';
@@ -70,18 +70,21 @@ export const AddEditBookmarkModal = (props) => {
70
70
  isEqual(props.selectedAccounts.map((a) => a.accountNumber).sort(), localSelectedBookmarks.map((a) => a.accountNumber).sort()) &&
71
71
  selectedGroup === ((_a = props.selectedAccounts[0]) === null || _a === void 0 ? void 0 : _a.bookmarkGroupName));
72
72
  };
73
- return (React.createElement(Modal, { id: "Add-edit-bookmark-modal", className: "pf-modal-overflow-visible", title: props.title, "aria-describedby": "Add-edit-bookmark-modal", isOpen: props.isOpen, onClose: close, showClose: true, onEscapePress: props.onClose, variant: ModalVariant.medium, actions: [
73
+ return (React.createElement(Modal, { id: "Add-edit-bookmark-modal", className: "pf-modal-overflow-visible", "aria-describedby": "Add-edit-bookmark-modal", isOpen: props.isOpen, onClose: close, onEscapePress: props.onClose, variant: ModalVariant.medium },
74
+ React.createElement(ModalHeader, null,
75
+ React.createElement("h2", null, props.title)),
76
+ React.createElement(ModalBody, null,
77
+ React.createElement("div", null,
78
+ React.createElement("div", { className: "pf-v6-u-mb-lg" },
79
+ React.createElement(BookmarkGroupSelector, { selectedGroup: selectedGroup, groups: props.groups, onGroupInputBoxChanged: onGroupInputBoxChanged, isInValid: isInValid && (isPresentInGroups || isEmpty(selectedGroup === null || selectedGroup === void 0 ? void 0 : selectedGroup.trim())), setIsInValid: setIsInValid, isPresentInGroups: isPresentInGroups })),
80
+ React.createElement("div", null,
81
+ React.createElement("label", { id: "add-bookmark-account-on-add-modal" },
82
+ React.createElement(Trans, null, "Account(s)"),
83
+ React.createElement("span", { className: "form-required", "aria-hidden": true }, "*")),
84
+ React.createElement(BookmarkAccountSelector, { defaultSelected: props.selectedAccounts, labelId: "add-bookmark-account-on-add-modal", bookmarkedGroupAccounts: props.bookmarkedGroupAccounts, onBookMarkAccountSelected: onBookMarkAccountSelected, addMode: props.addMode, isInValid: isInValid && isEmpty(localSelectedBookmarks) })))),
85
+ React.createElement(ModalFooter, null,
74
86
  React.createElement(Button, { key: "save", variant: ButtonVariant.primary, onClick: save, isDisabled: isInValid || isNothingIsChangedOnEditMode() },
75
87
  React.createElement(Trans, null, "Save")),
76
88
  React.createElement(Button, { key: "cancel", variant: props.addMode ? ButtonVariant.link : ButtonVariant.secondary, onClick: close },
77
- React.createElement(Trans, null, "Cancel")),
78
- ] },
79
- React.createElement("div", null,
80
- React.createElement("div", { className: "pf-v5-u-mb-lg" },
81
- React.createElement(BookmarkGroupSelector, { selectedGroup: selectedGroup, groups: props.groups, onGroupInputBoxChanged: onGroupInputBoxChanged, isInValid: isInValid && (isPresentInGroups || isEmpty(selectedGroup === null || selectedGroup === void 0 ? void 0 : selectedGroup.trim())), setIsInValid: setIsInValid, isPresentInGroups: isPresentInGroups })),
82
- React.createElement("div", null,
83
- React.createElement("label", { id: "add-bookmark-account-on-add-modal" },
84
- React.createElement(Trans, null, "Account(s)"),
85
- React.createElement("span", { className: "form-required", "aria-hidden": true }, "*")),
86
- React.createElement(BookmarkAccountSelector, { defaultSelected: props.selectedAccounts, labelId: "add-bookmark-account-on-add-modal", bookmarkedGroupAccounts: props.bookmarkedGroupAccounts, onBookMarkAccountSelected: onBookMarkAccountSelected, addMode: props.addMode, isInValid: isInValid && isEmpty(localSelectedBookmarks) })))));
89
+ React.createElement(Trans, null, "Cancel")))));
87
90
  };
@@ -1 +1 @@
1
- {"version":3,"file":"BookmarkAccountSelector.d.ts","sourceRoot":"","sources":["../../../../src/components/ManageBookmarkedAccountsTab/BookmarkAccountSelector.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,4CAA4C,CAAC;AAIhF,OAAO,EAAE,SAAS,EAAuB,MAAM,2BAA2B,CAAC;AAO3E,OAAO,KAAsC,MAAM,OAAO,CAAC;AAG3D,UAAU,MAAM;IACZ,uBAAuB,EAAE,SAAS,EAAE,CAAC;IACrC,iBAAiB,CAAC,EAAE,kBAAkB,CAAC;IACvC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,yBAAyB,CAAC,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,KAAK,IAAI,CAAC;IAC5D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,SAAS,EAAE,CAAC;IAC9B,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,qBA6PpD;yBA7Pe,uBAAuB"}
1
+ {"version":3,"file":"BookmarkAccountSelector.d.ts","sourceRoot":"","sources":["../../../../src/components/ManageBookmarkedAccountsTab/BookmarkAccountSelector.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,4CAA4C,CAAC;AAmBhF,OAAO,EAAE,SAAS,EAAuB,MAAM,2BAA2B,CAAC;AAO3E,OAAO,KAAsC,MAAM,OAAO,CAAC;AAG3D,UAAU,MAAM;IACZ,uBAAuB,EAAE,SAAS,EAAE,CAAC;IACrC,iBAAiB,CAAC,EAAE,kBAAkB,CAAC;IACvC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,yBAAyB,CAAC,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,KAAK,IAAI,CAAC;IAC5D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,SAAS,EAAE,CAAC;IAC9B,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,qBA6UpD;yBA7Ue,uBAAuB"}
@@ -8,9 +8,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  });
9
9
  };
10
10
  import { accounts } from '@cee-eng/hydrajs';
11
- import { Label, LabelGroup, Tooltip } from '@patternfly/react-core';
12
- import { Select, SelectOption, SelectVariant } from '@patternfly/react-core/deprecated';
11
+ import { Button, Label, LabelGroup, MenuToggle, Select, SelectList, SelectOption, Spinner, TextInputGroup, TextInputGroupMain, TextInputGroupUtilities, Tooltip, } from '@patternfly/react-core';
13
12
  import InfoCircleIcon from '@patternfly/react-icons/dist/js/icons/info-circle-icon';
13
+ import TimesCircleIcon from '@patternfly/react-icons/dist/js/icons/times-circle-icon';
14
+ import { useSelectKeyboardNavigator } from '@rh-support/components';
14
15
  import { sortAccountsByQuery } from '@rh-support/react-context';
15
16
  import assign from 'lodash/assign';
16
17
  import compact from 'lodash/compact';
@@ -21,15 +22,18 @@ import remove from 'lodash/remove';
21
22
  import React, { useEffect, useRef, useState } from 'react';
22
23
  import { Trans, useTranslation } from 'react-i18next';
23
24
  export function BookmarkAccountSelector(props) {
25
+ const { t } = useTranslation();
26
+ const textInputRef = useRef();
27
+ const abortControllerRef = useRef(undefined);
24
28
  const [options, setOptions] = useState([]);
25
29
  const [isSearching, setIsSearching] = useState(false);
26
- const abortControllerRef = useRef(undefined);
27
- const { t } = useTranslation();
28
30
  const [isOpen, setIsOpen] = useState(false);
29
31
  const [selected, setSelected] = useState([]);
30
- const onToggle = (isOpen) => setIsOpen(isOpen);
32
+ const [inputValue, setInputValue] = useState('');
33
+ const [activeItem, setActiveItem] = useState(null);
31
34
  const clearSelection = () => {
32
35
  setIsOpen(false);
36
+ setInputValue('');
33
37
  setSelected([]);
34
38
  props.onBookMarkAccountSelected([]);
35
39
  };
@@ -67,9 +71,9 @@ export function BookmarkAccountSelector(props) {
67
71
  const response = yield accounts.getAccounts(queryParams, controller.signal);
68
72
  const accountsResponse = response.items.map((account) => {
69
73
  const bookmarksMatch = props.bookmarkedGroupAccounts.filter((a) => a.accountNumber === account.accountNumber);
70
- const acountGroups = (bookmarksMatch || []).map((b) => b.bookmarkGroupName);
74
+ const accountGroups = (bookmarksMatch || []).map((b) => b.bookmarkGroupName);
71
75
  return bookmarksMatch.length > 0
72
- ? Object.assign(Object.assign({}, account), { bookmarkGroupName: acountGroups, isBookmarked: true, isBookmarkedAndHasGroup: acountGroups.length > 0 }) : Object.assign(Object.assign({}, account), { bookmarkGroupName: [], isBookmarked: false, isBookmarkedAndHasGroup: false });
76
+ ? Object.assign(Object.assign({}, account), { bookmarkGroupName: accountGroups, isBookmarked: true, isBookmarkedAndHasGroup: accountGroups.length > 0 }) : Object.assign(Object.assign({}, account), { bookmarkGroupName: [], isBookmarked: false, isBookmarkedAndHasGroup: false });
73
77
  });
74
78
  const sortedOptions = sortAccountsByQuery(accountsResponse, query, queryKey);
75
79
  setOptions(sortedOptions);
@@ -84,24 +88,61 @@ export function BookmarkAccountSelector(props) {
84
88
  }
85
89
  }
86
90
  });
87
- const onTypeaheadInputChanged = (input) => __awaiter(this, void 0, void 0, function* () {
88
- yield fetchAccounts(input);
91
+ const onSelect = (value) => {
92
+ if (value) {
93
+ const currentSelected = value;
94
+ const alreadySelected = find(selected, (account) => account.accountNumber === currentSelected.accountNumber);
95
+ if (alreadySelected)
96
+ return;
97
+ const selectedAccounts = [
98
+ ...selected,
99
+ Object.assign(Object.assign({}, currentSelected), { bookmarkId: currentSelected.bookmarkId || undefined, rootBookmarkId: currentSelected.rootBookmarkId || undefined }),
100
+ ];
101
+ setSelected(selectedAccounts);
102
+ props.onBookMarkAccountSelected(selectedAccounts);
103
+ setIsOpen(false);
104
+ setInputValue('');
105
+ }
106
+ };
107
+ const { focusedItemIndex, onInputKeyDown, setFocusedItemIndex } = useSelectKeyboardNavigator({
108
+ list: options,
109
+ isOpen,
110
+ ignoreResetOnListChange: false,
111
+ resetIndexOnClose: true,
112
+ isDisabled: props.isDisabled,
113
+ setIsOpen,
114
+ onSelect: (value) => onSelect(value),
89
115
  });
90
- // this ref is used to call clearSelection() outside component
91
- props.clearRef.current = clearSelection;
92
- const debounceFn = debounce(onTypeaheadInputChanged, 500);
93
- const onSelect = (event, currentSelected) => {
94
- const alreadySelected = find(selected, (account) => account.accountNumber === currentSelected.accountNumber);
95
- if (alreadySelected)
96
- return;
97
- const selectedAccounts = [
98
- ...selected,
99
- Object.assign(Object.assign({}, currentSelected), { bookmarkId: currentSelected.bookmarkId || undefined, rootBookmarkId: currentSelected.rootBookmarkId || undefined }),
100
- ];
101
- setSelected(selectedAccounts);
102
- props.onBookMarkAccountSelected(selectedAccounts);
103
- setIsOpen(false);
116
+ const onToggleClick = (e) => {
117
+ e.stopPropagation();
118
+ setIsOpen(!isOpen);
104
119
  };
120
+ const removeAccountLabel = (event, removedAccount) => {
121
+ event.stopPropagation();
122
+ const updatedSelectedAccounts = remove(selected, (account) => account.accountNumber !== removedAccount.accountNumber);
123
+ setSelected(updatedSelectedAccounts);
124
+ props.onBookMarkAccountSelected(updatedSelectedAccounts);
125
+ };
126
+ const debounceFn = debounce((value) => fetchAccounts(value), 500);
127
+ const onTextInputChange = (_event, value) => {
128
+ setInputValue(value);
129
+ debounceFn(value);
130
+ };
131
+ const toggle = (toggleRef) => (React.createElement(MenuToggle, { variant: "typeahead", onClick: onToggleClick, innerRef: toggleRef, isExpanded: isOpen, isFullWidth: true },
132
+ React.createElement(TextInputGroup, { isPlain: true },
133
+ React.createElement(TextInputGroupMain, Object.assign({ value: inputValue, onChange: onTextInputChange, onClick: (e) => {
134
+ e.stopPropagation();
135
+ setIsOpen(true);
136
+ setFocusedItemIndex(null);
137
+ setActiveItem(null);
138
+ }, onKeyDown: onInputKeyDown, id: "bookmark-account-select-input", autoComplete: "off", innerRef: textInputRef, placeholder: t('Search for account names or numbers'), role: "combobox", isExpanded: isOpen, "aria-controls": "bookmark-account-select-listbox" }, (activeItem && { 'aria-activedescendant': activeItem })),
139
+ React.createElement(LabelGroup, { "aria-label": "Selected accounts" }, selected.map((account, index) => (React.createElement(Label, { key: index, color: "teal", onClose: (ev) => removeAccountLabel(ev, account) },
140
+ account.name,
141
+ " (",
142
+ account.accountNumber,
143
+ ")"))))),
144
+ selected.length > 0 && (React.createElement(TextInputGroupUtilities, null,
145
+ React.createElement(Button, { variant: "plain", onClick: clearSelection, "aria-label": "Clear input value", icon: React.createElement(TimesCircleIcon, { "aria-hidden": true }) }))))));
105
146
  const duplicateAccounts = (props.selectedGroup &&
106
147
  props.addMode &&
107
148
  props.bookmarkedGroupAccounts
@@ -110,57 +151,55 @@ export function BookmarkAccountSelector(props) {
110
151
  })
111
152
  .map((a) => a.accountNumber)) ||
112
153
  [];
113
- const removeAccountLabel = (event, removedAccount) => {
114
- event.stopPropagation();
115
- const updatedSelectedAccounts = remove(selected, (account) => account.accountNumber !== removedAccount.accountNumber);
116
- setSelected(updatedSelectedAccounts);
117
- props.onBookMarkAccountSelected(updatedSelectedAccounts);
118
- };
119
- const labelGroupComponent = () => {
120
- return (React.createElement(LabelGroup, { numLabels: 2 }, (selected || []).map((currentLabel) => (React.createElement(Label, { key: currentLabel.accountNumber, onClose: (event) => removeAccountLabel(event, currentLabel), color: "cyan", onClick: (event) => event.stopPropagation() },
121
- currentLabel.name,
122
- " (",
123
- currentLabel.accountNumber,
124
- ")")))));
125
- };
154
+ const renderAccountOption = (account, index) => (React.createElement(SelectOption, { value: account, key: index, isFocused: focusedItemIndex !== null && focusedItemIndex === index, id: `bookmark-account-${account.accountNumber}` },
155
+ React.createElement("div", null,
156
+ React.createElement("div", { className: "pf-v6-u-color-100 pf-v6-u-font-size-sm" },
157
+ account.name,
158
+ " (",
159
+ account.accountNumber,
160
+ ")"),
161
+ React.createElement("div", null, account.bookmarkGroupName.length === 0 ? (React.createElement("span", { className: "pf-v6-u-color-400" },
162
+ React.createElement(Trans, null, "This account has not been bookmarked."))) : account.bookmarkGroupName.length > 2 ? (React.createElement("div", null,
163
+ React.createElement(Tooltip, { isContentLeftAligned: true, content: Array.isArray(account.bookmarkGroupName) ? (account.bookmarkGroupName.map((group) => React.createElement("div", { key: group }, group))) : (React.createElement("div", null, account.bookmarkGroupName)) },
164
+ React.createElement(Label, { color: "purple", icon: React.createElement(InfoCircleIcon, null), key: `${account.accountNumber}${account.bookmarkGroupName}` },
165
+ "Bookmarked ",
166
+ account.bookmarkGroupName.length,
167
+ " times")))) : Array.isArray(account.bookmarkGroupName) ? (account.bookmarkGroupName.map((group) => !isEmpty(group) && (React.createElement(Label, { color: "purple", key: `${account.accountNumber}-${group}` }, group)))) : (!isEmpty(account.bookmarkGroupName) && (React.createElement(Label, { color: "purple", key: `${account.accountNumber}-${account.bookmarkGroupName}` }, account.bookmarkGroupName)))))));
126
168
  useEffect(() => {
127
169
  setSelected(props.defaultSelected || []);
128
170
  }, [props.defaultSelected]);
129
- // when a group is added or removed from account we need to update dropdown
130
- // options to show correct group
131
171
  useEffect(() => {
132
- let newOptions = [];
133
- setOptions(undefined);
134
- // if group is not empty then add it
135
- options.forEach((option) => {
136
- const updatedGroupNames = compact(props.bookmarkedGroupAccounts
137
- .filter((b) => b.accountNumber === option.accountNumber)
138
- .map((b) => b.bookmarkGroupName));
139
- newOptions = [
140
- ...newOptions,
141
- Object.assign(Object.assign({}, option), { bookmarkGroupName: compact(updatedGroupNames), isBookmarked: true, isBookmarkedAndHasGroup: !!updatedGroupNames.length }),
142
- ];
143
- });
144
- setOptions(newOptions);
172
+ if (options.length > 0) {
173
+ const newOptions = options.map((option) => {
174
+ const updatedGroupNames = compact(props.bookmarkedGroupAccounts
175
+ .filter((b) => b.accountNumber === option.accountNumber)
176
+ .map((b) => b.bookmarkGroupName));
177
+ return Object.assign(Object.assign({}, option), { bookmarkGroupName: compact(updatedGroupNames), isBookmarked: true, isBookmarkedAndHasGroup: !!updatedGroupNames.length });
178
+ });
179
+ setOptions(newOptions);
180
+ }
145
181
  // eslint-disable-next-line react-hooks/exhaustive-deps
146
182
  }, [props.bookmarkedGroupAccounts]);
147
- const titleId = 'multi-typeahead-bookmark-chip-group-props-id';
183
+ // Update activeItem when focusedItemIndex changes
184
+ useEffect(() => {
185
+ var _a;
186
+ if (focusedItemIndex !== null && options[focusedItemIndex]) {
187
+ setActiveItem(`bookmark-account-${(_a = options[focusedItemIndex]) === null || _a === void 0 ? void 0 : _a.accountNumber}`);
188
+ }
189
+ else {
190
+ setActiveItem(null);
191
+ }
192
+ }, [focusedItemIndex, options]);
193
+ props.clearRef.current = clearSelection;
148
194
  return (React.createElement(React.Fragment, null,
149
- React.createElement("span", { id: titleId, hidden: true }, "Select a state"),
150
- React.createElement(Select, Object.assign({ chipGroupComponent: labelGroupComponent(), variant: SelectVariant.typeaheadMulti, typeAheadAriaLabel: t('Search for account names or numbers'), onToggle: (_event, isOpen) => onToggle(isOpen), onSelect: onSelect, onClear: clearSelection, "data-tracking-id": props.labelId, selections: selected, isOpen: isOpen, "aria-labelledby": titleId, placeholderText: t('Search for account names or numbers'), hasInlineFilter: false, onTypeaheadInputChanged: debounceFn, onFilter: () => undefined, "aria-describedby": "clusterID-validate-helper" }, (isSearching && { loadingVariant: 'spinner' })), options.map((account, index) => (React.createElement(SelectOption, { value: account, key: index },
151
- React.createElement("div", null,
152
- React.createElement("div", { className: "pf-v5-u-color-100 pf-v5-u-font-size-sm" },
153
- account.name,
154
- " (",
155
- account.accountNumber,
156
- ")"),
157
- React.createElement("div", null, account.bookmarkGroupName.length === 0 ? (React.createElement("span", { className: "pf-v5-u-color-400" },
158
- React.createElement(Trans, null, "This account has not been bookmarked."))) : account.bookmarkGroupName.length > 2 ? (React.createElement("div", null,
159
- React.createElement(Tooltip, { isContentLeftAligned: true, content: account.bookmarkGroupName.map((group) => (React.createElement("div", null, group))) },
160
- React.createElement(Label, { color: "purple", icon: React.createElement(InfoCircleIcon, null), key: `${account.accountNumber}${account.bookmarkGroupName}` },
161
- "Bookmarked ",
162
- account.bookmarkGroupName.length,
163
- " times")))) : (account.bookmarkGroupName.map((group) => !isEmpty(group) && (React.createElement(Label, { color: "purple", key: `${account.accountNumber}-${group}` }, group)))))))))),
195
+ React.createElement(Select, { id: "bookmark-account-select", isOpen: isOpen, selected: selected, onSelect: (_, value) => onSelect(value), toggle: toggle, onOpenChange: (nextOpen) => {
196
+ setIsOpen(nextOpen);
197
+ if (!nextOpen) {
198
+ setInputValue('');
199
+ }
200
+ }, isScrollable: true },
201
+ React.createElement(SelectList, { id: "bookmark-account-select-listbox" }, isSearching ? (React.createElement(SelectOption, { isLoading: true, value: "loader", className: "pf-v6-u-text-align-center" },
202
+ React.createElement(Spinner, { size: "lg" }))) : options.length > 0 ? (options.map((account, index) => renderAccountOption(account, index))) : (React.createElement(SelectOption, { value: '', key: 'no-value' }, "No results found")))),
164
203
  props.isInValid && (React.createElement("p", { className: "form-instructions form-invalid" },
165
204
  React.createElement(Trans, null, "Select one or more accounts to bookmark"))),
166
205
  duplicateAccounts.length !== 0 && (React.createElement("p", { className: "form-instructions" },
@@ -1 +1 @@
1
- {"version":3,"file":"BookmarkGroupSelector.d.ts","sourceRoot":"","sources":["../../../../src/components/ManageBookmarkedAccountsTab/BookmarkGroupSelector.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAGnD,UAAU,MAAM;IACZ,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,sBAAsB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IAC5D,iBAAiB,EAAE,OAAO,CAAC;CAC9B;AAED,QAAA,MAAM,qBAAqB,UAAW,MAAM,sBAsD3C,CAAC;AAEF,OAAO,EAAE,qBAAqB,EAAE,CAAC"}
1
+ {"version":3,"file":"BookmarkGroupSelector.d.ts","sourceRoot":"","sources":["../../../../src/components/ManageBookmarkedAccountsTab/BookmarkGroupSelector.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAGnD,UAAU,MAAM;IACZ,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,sBAAsB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IAC5D,iBAAiB,EAAE,OAAO,CAAC;CAC9B;AAED,QAAA,MAAM,qBAAqB,GAAI,OAAO,MAAM,sBAsD3C,CAAC;AAEF,OAAO,EAAE,qBAAqB,EAAE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ManageGroupedBookmarkedAccountsTab.d.ts","sourceRoot":"","sources":["../../../../src/components/ManageBookmarkedAccountsTab/ManageGroupedBookmarkedAccountsTab.tsx"],"names":[],"mappings":"AAwCA,OAAO,KAA2B,MAAM,OAAO,CAAC;AAOhD,UAAU,MAAM;IACZ,yBAAyB,EAAE,OAAO,CAAC;CACtC;AAED,wBAAgB,kCAAkC,CAAC,EAAE,yBAAyB,EAAE,EAAE,MAAM,qBAqZvF"}
1
+ {"version":3,"file":"ManageGroupedBookmarkedAccountsTab.d.ts","sourceRoot":"","sources":["../../../../src/components/ManageBookmarkedAccountsTab/ManageGroupedBookmarkedAccountsTab.tsx"],"names":[],"mappings":"AAwCA,OAAO,KAA2B,MAAM,OAAO,CAAC;AAOhD,UAAU,MAAM;IACZ,yBAAyB,EAAE,OAAO,CAAC;CACtC;AAED,wBAAgB,kCAAkC,CAAC,EAAE,yBAAyB,EAAE,EAAE,MAAM,qBAoZvF"}