@rh-support/manage 2.5.230 → 2.5.232

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 (24) hide show
  1. package/lib/esm/ManageTabs.d.ts.map +1 -1
  2. package/lib/esm/ManageTabs.js +30 -17
  3. package/lib/esm/components/Groups/DefualtGroupSwitch/DefaultGroupSwitch.d.ts +4 -3
  4. package/lib/esm/components/Groups/DefualtGroupSwitch/DefaultGroupSwitch.d.ts.map +1 -1
  5. package/lib/esm/components/Groups/DefualtGroupSwitch/DefaultGroupSwitch.js +15 -13
  6. package/lib/esm/components/Groups/GroupSelect/GroupSelect.d.ts.map +1 -1
  7. package/lib/esm/components/Groups/GroupSelect/GroupSelect.js +107 -85
  8. package/lib/esm/components/Groups/ManageGroupUsers/ManageGroupUsers.d.ts.map +1 -1
  9. package/lib/esm/components/Groups/ManageGroupUsers/ManageGroupUsers.js +45 -31
  10. package/lib/esm/components/ManagePreferences/sections/PreferencesACL.d.ts.map +1 -1
  11. package/lib/esm/components/ManagePreferences/sections/PreferencesACL.js +3 -4
  12. package/lib/esm/components/ManagePreferences/sections/PreferencesCaseCreate.d.ts.map +1 -1
  13. package/lib/esm/components/ManagePreferences/sections/PreferencesCaseCreate.js +4 -2
  14. package/lib/esm/components/ManagePreferences/sections/PreferencesCaseView.d.ts.map +1 -1
  15. package/lib/esm/components/ManagePreferences/sections/PreferencesCaseView.js +3 -4
  16. package/lib/esm/hooks/useCaseGroupGraphQL.d.ts +32 -0
  17. package/lib/esm/hooks/useCaseGroupGraphQL.d.ts.map +1 -0
  18. package/lib/esm/hooks/useCaseGroupGraphQL.js +94 -0
  19. package/lib/esm/hooks/useVersionsDiffer.d.ts.map +1 -1
  20. package/lib/esm/scss/_main.scss +5 -0
  21. package/lib/esm/utils/caseGroupMapper.d.ts +17 -0
  22. package/lib/esm/utils/caseGroupMapper.d.ts.map +1 -0
  23. package/lib/esm/utils/caseGroupMapper.js +47 -0
  24. package/package.json +9 -8
@@ -1 +1 @@
1
- {"version":3,"file":"ManageTabs.d.ts","sourceRoot":"","sources":["../../src/ManageTabs.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAExC,OAAO,EAAE,mBAAmB,EAAa,MAAM,kBAAkB,CAAC;AAclE,UAAU,MAAM;IACZ,UAAU,EAAE,mBAAmB,CAAC,EAAE,CAAC,CAAC;IACpC,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,qBAyMvC"}
1
+ {"version":3,"file":"ManageTabs.d.ts","sourceRoot":"","sources":["../../src/ManageTabs.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAExC,OAAO,EAAE,mBAAmB,EAAa,MAAM,kBAAkB,CAAC;AAelE,UAAU,MAAM;IACZ,UAAU,EAAE,mBAAmB,CAAC,EAAE,CAAC,CAAC;IACpC,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,qBA6MvC"}
@@ -1,6 +1,6 @@
1
1
  import { Tab, TabContent, Tabs, TabsComponent, TabTitleText } from '@patternfly/react-core';
2
2
  import { ErrorBoundary, useDocumentTitle } from '@rh-support/components';
3
- import { ability, CaseDetailsFields, resourceActions, resources } from '@rh-support/user-permissions';
3
+ import { ability, resourceActions, resources } from '@rh-support/user-permissions';
4
4
  import map from 'lodash/map';
5
5
  import React, { useState } from 'react';
6
6
  import { Trans, useTranslation } from 'react-i18next';
@@ -9,10 +9,11 @@ import { ConfigsTable } from './components/Configs/ConfigsTable';
9
9
  import { ManageGroupUsers } from './components/Groups/ManageGroupUsers';
10
10
  import { ManageGroupedBookmarkedAccountsTab } from './components/ManageBookmarkedAccountsTab';
11
11
  import { ExpiredContentManagement } from './components/ManageExpiredContents/ExpiredContentManagement';
12
- import { ManagePartnerships } from './components/ManagePartnerships/index';
12
+ // TODO: Uncomment when partnerships tab is re-implemented
13
+ // import { ManagePartnerships } from './components/ManagePartnerships/index';
13
14
  import { ManagePreferences } from './components/ManagePreferences';
14
15
  import { TagsManagement } from './components/ManageTags';
15
- import { NotificationEmails } from './components/NotificationEmails/index';
16
+ // import { NotificationEmails } from './components/NotificationEmails/index';
16
17
  import { TopContentManagement } from './components/TopContentManagement';
17
18
  import { PageTitle } from './constants/pageTitle';
18
19
  import { Routes } from './Routes';
@@ -21,15 +22,24 @@ export function ManageTabs(props) {
21
22
  const [activeTabKey, setActiveTabKey] = useState(0);
22
23
  const { activeTab } = useParams();
23
24
  const { t } = useTranslation();
24
- const { groupsRoute, bookmarkedAccountsRoute, topContentRoute, notificationEmailsRoute, preferencesRoute, configsRoute, partnershipsRoute, tagsManagerRoute, expiredContentRoute, } = Routes.getPaths();
25
+ const { groupsRoute, bookmarkedAccountsRoute, topContentRoute,
26
+ // notificationEmailsRoute,
27
+ preferencesRoute, configsRoute,
28
+ // partnershipsRoute, // TODO: Uncomment when partnerships tab is re-implemented
29
+ tagsManagerRoute, expiredContentRoute, } = Routes.getPaths();
25
30
  useDocumentTitle(PageTitle.MANAGE);
26
31
  const canViewManageTab = ability.can(resourceActions.READ, resources.MANAGE);
27
32
  const canViewManageTopContent = ability.can(resourceActions.READ, resources.TOP_CONTENT) && canViewManageTab;
28
33
  const canViewCaseGroups = ability.can(resourceActions.READ, resources.CASE_GROUPS) && canViewManageTab;
29
34
  const canManageBookmarkAccounts = ability.can(resourceActions.CREATE, resources.BOOKMARK_ACCOUNTS) && canViewManageTab;
30
- const canViewEmailNotificationTab = ability.can(resourceActions.READ, resources.NOTIFICATION_EMAIL);
31
- const canViewPartnershipsTab = ability.can(resourceActions.READ, resources.PARTNERSHIPS);
32
- const canAddCustomNotification = ability.can(resourceActions.PATCH, resources.CASE_DETAILS, CaseDetailsFields.CASE_DETAILS_SEND_NOTIFICATIONS);
35
+ // const canViewEmailNotificationTab = ability.can(resourceActions.READ, resources.NOTIFICATION_EMAIL);
36
+ // TODO: Uncomment when partnerships tab is re-implemented
37
+ // const canViewPartnershipsTab = ability.can(resourceActions.READ, resources.PARTNERSHIPS);
38
+ // const canAddCustomNotification = ability.can(
39
+ // resourceActions.PATCH,
40
+ // resources.CASE_DETAILS,
41
+ // CaseDetailsFields.CASE_DETAILS_SEND_NOTIFICATIONS
42
+ // );
33
43
  const canViewConfigsTab = ability.can(resourceActions.READ, resources.APP_INTERNAL_CONFIGS);
34
44
  const tabsToRender = [];
35
45
  canManageBookmarkAccounts &&
@@ -50,6 +60,7 @@ export function ManageTabs(props) {
50
60
  component: React.createElement(ManageGroupUsers, null),
51
61
  id: 'manage-groups',
52
62
  });
63
+ /* TODO: Re-enable notification emails tab when ready
53
64
  canViewEmailNotificationTab &&
54
65
  canAddCustomNotification &&
55
66
  tabsToRender.push({
@@ -57,18 +68,20 @@ export function ManageTabs(props) {
57
68
  key: 'notification-emails-tab',
58
69
  'data-tracking-id': 'notification-emails-tab',
59
70
  routePath: notificationEmailsRoute,
60
- component: React.createElement(NotificationEmails, null),
71
+ component: <NotificationEmails />,
61
72
  id: 'notification-emails',
62
73
  });
63
- canViewPartnershipsTab &&
64
- tabsToRender.push({
65
- title: 'Partnerships',
66
- key: 'partnerships-tab',
67
- 'data-tracking-id': 'partnerships-tab',
68
- routePath: partnershipsRoute,
69
- component: React.createElement(ManagePartnerships, null),
70
- id: 'partnerships',
71
- });
74
+ */
75
+ // TODO: Uncomment when partnerships tab is re-implemented
76
+ // canViewPartnershipsTab &&
77
+ // tabsToRender.push({
78
+ // title: 'Partnerships',
79
+ // key: 'partnerships-tab',
80
+ // 'data-tracking-id': 'partnerships-tab',
81
+ // routePath: partnershipsRoute,
82
+ // component: <ManagePartnerships />,
83
+ // id: 'partnerships',
84
+ // });
72
85
  tabsToRender.push({
73
86
  title: 'Preferences',
74
87
  key: 'preferences-tab',
@@ -1,10 +1,11 @@
1
- import { ICaseGroup, IGroupUser } from '@cee-eng/hydrajs/@types/api/public/caseGroups';
1
+ import { ICaseGroup } from '@cee-eng/hydrajs/@types/api/public/caseGroups';
2
2
  import React from 'react';
3
+ import type { IGroupUserWithContactId } from '../../../utils/caseGroupMapper';
3
4
  interface IProps {
4
5
  group: ICaseGroup;
5
- user: IGroupUser;
6
+ user: IGroupUserWithContactId;
6
7
  id: string;
7
- onToggle: (user: IGroupUser, isChecked: boolean) => void;
8
+ onToggle: (user: IGroupUserWithContactId, isChecked: boolean) => void;
8
9
  }
9
10
  export declare const DefaultGroupSwitch: (props: IProps) => React.JSX.Element;
10
11
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"DefaultGroupSwitch.d.ts","sourceRoot":"","sources":["../../../../../src/components/Groups/DefualtGroupSwitch/DefaultGroupSwitch.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,+CAA+C,CAAC;AAIvF,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,UAAU,MAAM;IACZ,KAAK,EAAE,UAAU,CAAC;IAClB,IAAI,EAAE,UAAU,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;CAC5D;AAED,eAAO,MAAM,kBAAkB,GAAI,OAAO,MAAM,sBA+C/C,CAAC"}
1
+ {"version":3,"file":"DefaultGroupSwitch.d.ts","sourceRoot":"","sources":["../../../../../src/components/Groups/DefualtGroupSwitch/DefaultGroupSwitch.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,+CAA+C,CAAC;AAG3E,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AAE9E,UAAU,MAAM;IACZ,KAAK,EAAE,UAAU,CAAC;IAClB,IAAI,EAAE,uBAAuB,CAAC;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,CAAC,IAAI,EAAE,uBAAuB,EAAE,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;CACzE;AAED,eAAO,MAAM,kBAAkB,GAAI,OAAO,MAAM,sBA2C/C,CAAC"}
@@ -7,33 +7,35 @@ 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
10
  import { Switch } from '@patternfly/react-core';
12
- import { LoadingIndicator, ToastNotification, useFetch } from '@rh-support/components';
13
- import { useGlobalStateContext } from '@rh-support/react-context';
11
+ import { LoadingIndicator, ToastNotification } from '@rh-support/components';
14
12
  import React from 'react';
15
13
  import { useTranslation } from 'react-i18next';
14
+ import { useToggleDefaultGroup } from '../../../hooks/useCaseGroupGraphQL';
16
15
  export const DefaultGroupSwitch = (props) => {
17
- const { globalMetadataState: { loggedInUsersAccount }, } = useGlobalStateContext();
18
16
  const { group, id, user, onToggle } = props;
19
17
  // @ts-ignore
20
18
  const { t } = useTranslation();
21
- const toggleDefaultGroupFetch = useFetch(publicApi.caseGroups.toggleDefaultGroup, {
22
- propgateErrors: true,
23
- });
24
- // Handle Toggle
25
- const toggleDefault = (isChecked) => __awaiter(void 0, void 0, void 0, function* () {
19
+ const { toggleDefault, loading: isFetching } = useToggleDefaultGroup();
20
+ const handleToggle = (isChecked) => __awaiter(void 0, void 0, void 0, function* () {
26
21
  try {
27
22
  onToggle(user, isChecked);
28
- yield toggleDefaultGroupFetch.request(group.groupNum, user.ssoUsername, isChecked, loggedInUsersAccount.data.secureSupport);
23
+ const groupId = isChecked ? group.groupNum : null;
24
+ yield toggleDefault(user.contactSfId, groupId);
29
25
  ToastNotification.addSuccessMessage(t(`Default group updated successfully`));
30
26
  }
31
27
  catch (e) {
32
28
  onToggle(user, user.isDefault);
33
- ToastNotification.addDangerMessage(t('Could not toggle default status'));
29
+ const message = String((e === null || e === void 0 ? void 0 : e.message) || '');
30
+ if (message.includes('insufficient access rights')) {
31
+ ToastNotification.addDangerMessage(t('You do not have permission to change the default group for this user'));
32
+ }
33
+ else {
34
+ ToastNotification.addDangerMessage(t('Could not toggle default status'));
35
+ }
34
36
  }
35
37
  });
36
38
  return (React.createElement(React.Fragment, null,
37
- React.createElement(Switch, { "aria-label": "Toggle default group", "data-tracking-id": `group-user-toggle-default-${user.isDefault ? 'off' : 'on'}`, label: t('On'), id: id, isDisabled: user.access === false || user.write === false || toggleDefaultGroupFetch.isFetching, isChecked: user.isDefault, onChange: (_event, isChecked) => toggleDefault(isChecked) }),
38
- React.createElement(LoadingIndicator, { show: toggleDefaultGroupFetch.isFetching, size: "xs" })));
39
+ React.createElement(Switch, { "aria-label": "Toggle default group", "data-tracking-id": `group-user-toggle-default-${user.isDefault ? 'off' : 'on'}`, label: t('On'), id: id, isDisabled: isFetching, isChecked: user.isDefault, onChange: (_event, isChecked) => handleToggle(isChecked) }),
40
+ React.createElement(LoadingIndicator, { show: isFetching, size: "xs" })));
39
41
  };
@@ -1 +1 @@
1
- {"version":3,"file":"GroupSelect.d.ts","sourceRoot":"","sources":["../../../../../src/components/Groups/GroupSelect/GroupSelect.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,+CAA+C,CAAC;AAwC3E,OAAO,KAAmD,MAAM,OAAO,CAAC;AAKxE,UAAU,MAAM;IACZ,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,KAAK,IAAI,CAAC;CAChD;AAKD,eAAO,MAAM,WAAW,GAAI,OAAO,MAAM,sBAmjBxC,CAAC"}
1
+ {"version":3,"file":"GroupSelect.d.ts","sourceRoot":"","sources":["../../../../../src/components/Groups/GroupSelect/GroupSelect.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,+CAA+C,CAAC;AAsC3E,OAAO,KAAmD,MAAM,OAAO,CAAC;AAMxE,UAAU,MAAM;IACZ,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,KAAK,IAAI,CAAC;CAChD;AAKD,eAAO,MAAM,WAAW,GAAI,OAAO,MAAM,sBA4kBxC,CAAC"}
@@ -7,26 +7,28 @@ 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';
10
+ import { useApolloClient } from '@apollo/client/react';
11
11
  import { Button, Divider, Dropdown, MenuContent, MenuItem, MenuList, MenuToggle, Select, SelectList, SelectOption, Spinner, TextInput, TextInputGroup, TextInputGroupMain, TextInputGroupUtilities, } from '@patternfly/react-core';
12
12
  import CogIcon from '@patternfly/react-icons/dist/js/icons/cog-icon';
13
13
  import TimesIcon from '@patternfly/react-icons/dist/js/icons/times-icon';
14
- import { AlertMessage, AlertType, ToastNotification, useConfirmation, useFetch, usePrevious, useSelectKeyboardNavigator, } from '@rh-support/components';
14
+ import { AlertMessage, AlertType, ToastNotification, useConfirmation, usePrevious, useSelectKeyboardNavigator, } from '@rh-support/components';
15
15
  import { fetchCaseGroupsForSSO, setCaseGroups, useGlobalDispatchContext, useGlobalStateContext, } from '@rh-support/react-context';
16
16
  import { ability, resourceActions, resources } from '@rh-support/user-permissions';
17
- import { haventLoadedMetadata } from '@rh-support/utils';
18
17
  import find from 'lodash/find';
19
18
  import isEmpty from 'lodash/isEmpty';
20
19
  import React, { useCallback, useEffect, useRef, useState } from 'react';
21
20
  import { Trans, useTranslation } from 'react-i18next';
22
21
  import { GroupSelectActions } from '../../../constants/GroupSelectActions';
22
+ import { useCreateCaseGroup, useDeleteCaseGroup, useRenameCaseGroup } from '../../../hooks/useCaseGroupGraphQL';
23
23
  const actions = GroupSelectActions;
24
24
  const unGroupedCaseGroupNumber = '-1';
25
25
  export const GroupSelect = (props) => {
26
+ var _a;
26
27
  const { t } = useTranslation();
27
28
  const { onSelect: onSelectProp } = props;
28
29
  const manageActionsRef = useRef();
29
- const { globalMetadataState: { caseGroups, loggedInUserJwtToken }, } = useGlobalStateContext();
30
+ const apolloClient = useApolloClient();
31
+ const { globalMetadataState: { caseGroups, loggedInUserJwtToken, loggedInUsersAccount }, } = useGlobalStateContext();
30
32
  const dispatch = useGlobalDispatchContext();
31
33
  const selectAGroupText = caseGroups.isFetching
32
34
  ? t('Loading groups')
@@ -37,11 +39,22 @@ export const GroupSelect = (props) => {
37
39
  const confirmation = useConfirmation();
38
40
  const [input, setInput] = useState('');
39
41
  const [shouldFilter, setShouldFilter] = useState(false);
40
- // Fetch groups on init
42
+ const accountId = (_a = loggedInUsersAccount === null || loggedInUsersAccount === void 0 ? void 0 : loggedInUsersAccount.data) === null || _a === void 0 ? void 0 : _a.salesforceAccountId;
43
+ // GraphQL hooks for mutations
44
+ const { createGroup: createGroupMutation, loading: createLoading } = useCreateCaseGroup();
45
+ const { renameGroup: renameGroupMutation, loading: renameLoading } = useRenameCaseGroup();
46
+ const { deleteGroup: deleteGroupMutation, loading: deleteLoading } = useDeleteCaseGroup();
47
+ const hasFetchedFromGraphQL = useRef(false);
48
+ // Always fetch groups from GraphQL — never rely on potentially stale Hydra data
49
+ useEffect(() => {
50
+ if (!hasFetchedFromGraphQL.current && apolloClient && accountId) {
51
+ hasFetchedFromGraphQL.current = true;
52
+ fetchCaseGroupsForSSO(dispatch, loggedInUserJwtToken.preferred_username, apolloClient, accountId);
53
+ }
54
+ }, [dispatch, loggedInUserJwtToken.preferred_username, apolloClient, accountId]);
55
+ // Set default group once groups are loaded
41
56
  useEffect(() => {
42
57
  var _a, _b;
43
- if (haventLoadedMetadata(caseGroups, (data) => data === undefined))
44
- fetchCaseGroupsForSSO(dispatch, loggedInUserJwtToken.preferred_username);
45
58
  if (isEmpty(selectedGroup) && !isEmpty(caseGroups) && ((_a = caseGroups === null || caseGroups === void 0 ? void 0 : caseGroups.data) === null || _a === void 0 ? void 0 : _a.length) > 0) {
46
59
  const defaultCaseGroup = find(caseGroups === null || caseGroups === void 0 ? void 0 : caseGroups.data, (g) => g.isDefault);
47
60
  const newSelectedGroup = (defaultCaseGroup === null || defaultCaseGroup === void 0 ? void 0 : defaultCaseGroup.groupNum) === '-1'
@@ -53,7 +66,7 @@ export const GroupSelect = (props) => {
53
66
  }
54
67
  }
55
68
  // eslint-disable-next-line react-hooks/exhaustive-deps
56
- }, [dispatch, loggedInUserJwtToken, caseGroups]);
69
+ }, [caseGroups]);
57
70
  // handle dropdown open/close toggle
58
71
  const [isOpen, setIsOpen] = useState(false);
59
72
  // handle group selection
@@ -90,19 +103,10 @@ export const GroupSelect = (props) => {
90
103
  closeDropdown();
91
104
  setAction(action);
92
105
  };
93
- // fetch objects for apis
94
106
  const [showErrorMessage] = useState(false);
95
- const createGroupFetch = useFetch(publicApi.caseGroups.createGroup, { propgateErrors: true });
96
- const renameGroupFetch = useFetch(publicApi.caseGroups.renameGroup, { propgateErrors: true });
97
- const deleteGroupFetch = useFetch(publicApi.caseGroups.deleteGroup, { propgateErrors: true });
98
- const duplicateGroupFetch = useFetch(publicApi.caseGroups.createGroup, { propgateErrors: true });
99
107
  // group actions input state
100
108
  const textInputRef = useRef();
101
- const disableOnFetch = caseGroups.isFetching ||
102
- createGroupFetch.isFetching ||
103
- renameGroupFetch.isFetching ||
104
- deleteGroupFetch.isFetching ||
105
- duplicateGroupFetch.isFetching;
109
+ const disableOnFetch = caseGroups.isFetching || createLoading || renameLoading || deleteLoading;
106
110
  const onChange = (e, value) => {
107
111
  if (!showInput) {
108
112
  setIsOpen(true);
@@ -124,56 +128,77 @@ export const GroupSelect = (props) => {
124
128
  // eslint-disable-next-line react-hooks/exhaustive-deps
125
129
  }, [input, showInput]);
126
130
  // group actions
127
- function setGroupOnFetch(groupName) {
128
- return __awaiter(this, void 0, void 0, function* () {
129
- yield fetchCaseGroupsForSSO(dispatch, loggedInUserJwtToken.preferred_username);
130
- setSelectedGroup(groupName);
131
- });
132
- }
133
- function createGroup(groupName, ssoUsername) {
131
+ function createGroup(groupName) {
134
132
  return __awaiter(this, void 0, void 0, function* () {
133
+ if (!accountId) {
134
+ ToastNotification.addDangerMessage(t('There was an error while creating this group'));
135
+ return;
136
+ }
135
137
  try {
136
- yield createGroupFetch.request({ name: groupName, contactSsoName: ssoUsername });
138
+ const response = yield createGroupMutation(groupName, accountId);
139
+ const createdRecord = response.redhat_support_uiapi.CaseGroup__cCreate.RedHatSupportRecord;
137
140
  ToastNotification.addSuccessMessage(t('Group has been successfully created'));
138
- try {
139
- yield setGroupOnFetch(groupName);
140
- setShowDropdown(true);
141
- setShowInput(false);
142
- setSelectedGroup(groupName);
143
- }
144
- catch (error) {
145
- ToastNotification.addDangerMessage(t("We're having an issue finding this group's users"));
146
- onClear();
147
- }
141
+ const newGroup = {
142
+ groupNum: createdRecord.Id,
143
+ name: createdRecord.Name.value,
144
+ isPrivate: false,
145
+ isDefault: false,
146
+ defaultMembers: [],
147
+ members: [],
148
+ };
149
+ const updatedGroups = [...(caseGroups.data || []), newGroup];
150
+ setCaseGroups(dispatch, updatedGroups);
151
+ setShowDropdown(true);
152
+ setShowInput(false);
153
+ setSelectedGroup(groupName);
148
154
  }
149
155
  catch (e) {
150
- ToastNotification.addDangerMessage(t('There was an error while creating this group'));
156
+ const message = String((e === null || e === void 0 ? void 0 : e.message) || '');
157
+ if (message.includes('insufficient access rights')) {
158
+ ToastNotification.addDangerMessage(t('You do not have permission to create this group'));
159
+ }
160
+ else {
161
+ ToastNotification.addDangerMessage(t('There was an error while creating this group'));
162
+ }
151
163
  }
152
164
  });
153
165
  }
154
166
  const [action, setAction] = useState('');
155
167
  const isUserInputAGroup = () => (caseGroups.data || []).find((value) => value.name === input);
168
+ const handleDeleteGroup = () => __awaiter(void 0, void 0, void 0, function* () {
169
+ const groupToDelete = getGroup(selectedGroup);
170
+ yield confirmation({
171
+ catchOnCancel: true,
172
+ title: t('Delete group'),
173
+ description: (React.createElement(Trans, null,
174
+ "Are you sure you want to delete ",
175
+ React.createElement("strong", null, groupToDelete.name),
176
+ "?")),
177
+ });
178
+ yield deleteGroupMutation(groupToDelete.groupNum);
179
+ const index = (caseGroups.data || []).findIndex((value) => value.name === groupToDelete.name);
180
+ (caseGroups.data || []).splice(index, 1);
181
+ setCaseGroups(dispatch, caseGroups.data || []);
182
+ onClear();
183
+ ToastNotification.addSuccessMessage(t('Group has been successfully deleted'));
184
+ });
156
185
  const onAction = () => __awaiter(void 0, void 0, void 0, function* () {
186
+ const needsUniqueName = action === actions.create || action === actions.rename || action === actions.duplicate;
187
+ if (needsUniqueName && isUserInputAGroup()) {
188
+ ToastNotification.addWarningMessage(t('Group already exists'));
189
+ return;
190
+ }
157
191
  switch (action) {
158
192
  case actions.create: {
159
- if (isUserInputAGroup()) {
160
- ToastNotification.addWarningMessage(t('Group already exists'));
161
- break;
162
- }
163
- yield createGroup(input, loggedInUserJwtToken.preferred_username);
193
+ yield createGroup(input);
164
194
  setAction('');
165
195
  break;
166
196
  }
167
197
  case actions.rename: {
168
- if (isUserInputAGroup()) {
169
- ToastNotification.addWarningMessage(t('Group already exists'));
170
- break;
171
- }
172
198
  const previousGroup = selectedGroup;
173
199
  const group = getGroup(previousGroup);
174
200
  try {
175
- // change name in the current caseGroups list
176
- yield renameGroupFetch.request(input, group.groupNum, group.isPrivate);
201
+ yield renameGroupMutation(group.groupNum, input);
177
202
  const copyCaseGroups = [...(caseGroups.data || [])];
178
203
  const index = copyCaseGroups.findIndex((value) => value.name === previousGroup);
179
204
  copyCaseGroups[index].name = input;
@@ -185,7 +210,13 @@ export const GroupSelect = (props) => {
185
210
  ToastNotification.addSuccessMessage(t('Group has been renamed'));
186
211
  }
187
212
  catch (e) {
188
- ToastNotification.addDangerMessage(t('There was an error renaming this group '));
213
+ const message = String((e === null || e === void 0 ? void 0 : e.message) || '');
214
+ if (message.includes('insufficient access rights')) {
215
+ ToastNotification.addDangerMessage(t('You do not have permission to rename this group'));
216
+ }
217
+ else {
218
+ ToastNotification.addDangerMessage(t('There was an error renaming this group'));
219
+ }
189
220
  }
190
221
  finally {
191
222
  setAction('');
@@ -194,32 +225,13 @@ export const GroupSelect = (props) => {
194
225
  }
195
226
  case actions.delete: {
196
227
  try {
197
- const groupToDelete = getGroup(selectedGroup);
198
- try {
199
- // get confirmation on delete
200
- yield confirmation({
201
- catchOnCancel: true,
202
- title: t('Delete group'),
203
- description: (React.createElement(Trans, null,
204
- "Are you sure you want to delete ",
205
- React.createElement("strong", null, groupToDelete.name),
206
- "?")),
207
- });
208
- // delete action is confirmed
209
- yield deleteGroupFetch.request(groupToDelete.groupNum);
210
- // remove group from list
211
- const index = (caseGroups.data || []).findIndex((value) => value.name === groupToDelete.name);
212
- (caseGroups.data || []).splice(index, 1);
213
- setCaseGroups(dispatch, caseGroups.data || []);
214
- onClear();
215
- ToastNotification.addSuccessMessage(t('Group has been successfully deleted'));
216
- }
217
- catch (_a) {
218
- // user didn't confirm the delete action
219
- }
228
+ yield handleDeleteGroup();
220
229
  }
221
230
  catch (e) {
222
- ToastNotification.addDangerMessage(t('There was an error deleting this group'));
231
+ const message = String((e === null || e === void 0 ? void 0 : e.message) || '');
232
+ if (message.includes('insufficient access rights')) {
233
+ ToastNotification.addDangerMessage(t('You do not have permission to delete this group'));
234
+ }
223
235
  }
224
236
  finally {
225
237
  setAction('');
@@ -227,23 +239,37 @@ export const GroupSelect = (props) => {
227
239
  }
228
240
  }
229
241
  case actions.duplicate: {
230
- if (isUserInputAGroup()) {
231
- ToastNotification.addWarningMessage(t('Group already exists'));
242
+ if (!accountId) {
243
+ ToastNotification.addDangerMessage(t('There was an error while duplicating group'));
232
244
  break;
233
245
  }
234
246
  try {
235
- yield duplicateGroupFetch.request({
236
- name: input,
237
- contactSsoName: loggedInUserJwtToken.preferred_username,
238
- });
239
- yield setGroupOnFetch(input);
247
+ const dupResponse = yield createGroupMutation(input, accountId);
248
+ const dupRecord = dupResponse.redhat_support_uiapi.CaseGroup__cCreate.RedHatSupportRecord;
249
+ const dupGroup = {
250
+ groupNum: dupRecord.Id,
251
+ name: dupRecord.Name.value,
252
+ isPrivate: false,
253
+ isDefault: false,
254
+ defaultMembers: [],
255
+ members: [],
256
+ };
257
+ const updatedDupGroups = [...(caseGroups.data || []), dupGroup];
258
+ setCaseGroups(dispatch, updatedDupGroups);
240
259
  setShowDropdown(true);
241
260
  setShowInput(false);
261
+ setSelectedGroup(input);
242
262
  setInput('');
243
263
  ToastNotification.addSuccessMessage(t('Group has been successfully duplicated'));
244
264
  }
245
265
  catch (e) {
246
- ToastNotification.addDangerMessage(t('There was an error while duplicating group'));
266
+ const message = String((e === null || e === void 0 ? void 0 : e.message) || '');
267
+ if (message.includes('insufficient access rights')) {
268
+ ToastNotification.addDangerMessage(t('You do not have permission to duplicate this group'));
269
+ }
270
+ else {
271
+ ToastNotification.addDangerMessage(t('There was an error while duplicating group'));
272
+ }
247
273
  }
248
274
  finally {
249
275
  setAction('');
@@ -315,14 +341,11 @@ export const GroupSelect = (props) => {
315
341
  };
316
342
  const selectTypeahead = manageActionsRef.current.querySelector('input');
317
343
  if (!showInput) {
318
- // adds event listeners that prevent using enter to select a group.
319
344
  selectTypeahead.addEventListener('keydown', dontSubmitOnEnterCb);
320
345
  selectTypeahead.addEventListener('keyup', dontSubmitOnEnterCb);
321
346
  selectTypeahead.addEventListener('keypress', dontSubmitOnEnterCb);
322
347
  }
323
348
  else {
324
- // adds event listeners that allows submitting actions using enter on select
325
- // inupt used for getting user input for actions.
326
349
  selectTypeahead.addEventListener('keydown', submitOnEnterCb);
327
350
  }
328
351
  return () => {
@@ -336,7 +359,6 @@ export const GroupSelect = (props) => {
336
359
  }
337
360
  };
338
361
  }, [manageActionsRef, showInput]);
339
- //added for validation of new group name
340
362
  const containsOnlySpecialChars = (str) => {
341
363
  return /^[^a-zA-Z0-9]*$/.test(str);
342
364
  };
@@ -1 +1 @@
1
- {"version":3,"file":"ManageGroupUsers.d.ts","sourceRoot":"","sources":["../../../../../src/components/Groups/ManageGroupUsers/ManageGroupUsers.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAuC,MAAM,OAAO,CAAC;AAS5D,eAAO,MAAM,gBAAgB,yBA4L5B,CAAC"}
1
+ {"version":3,"file":"ManageGroupUsers.d.ts","sourceRoot":"","sources":["../../../../../src/components/Groups/ManageGroupUsers/ManageGroupUsers.tsx"],"names":[],"mappings":"AAKA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAYnD,eAAO,MAAM,gBAAgB,yBAyL5B,CAAC"}
@@ -7,39 +7,39 @@ 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
10
  import { SearchInput } from '@patternfly/react-core';
12
- import { ErrorBoundary, ToastNotification, useFetch, usePrevious } from '@rh-support/components';
11
+ import { ErrorBoundary, usePrevious } from '@rh-support/components';
13
12
  import { useGlobalStateContext } from '@rh-support/react-context';
14
13
  import isEmpty from 'lodash/isEmpty';
15
- import React, { useEffect, useMemo, useState } from 'react';
14
+ import React, { useEffect, useState } from 'react';
16
15
  import { Trans, useTranslation } from 'react-i18next';
17
16
  import { useLocation } from 'react-router-dom';
17
+ import { useCaseGroupMembers } from '../../../hooks/useCaseGroupGraphQL';
18
18
  import { ManageTable } from '../../ManageTable/ManageTable';
19
19
  import { DefaultGroupSwitch } from '../DefualtGroupSwitch';
20
20
  import { GroupSelect } from '../GroupSelect';
21
- import { GroupUserPermissionsSelect } from '../GroupUserPermissionsSelect';
21
+ // TODO: Uncomment when updateUsers is migrated to GraphQL
22
+ // import { GroupUserPermissionsSelect } from '../GroupUserPermissionsSelect';
22
23
  export const ManageGroupUsers = () => {
23
24
  const { t } = useTranslation();
24
25
  const location = useLocation();
25
26
  const { globalMetadataState: { loggedInUsersAccount }, } = useGlobalStateContext();
26
27
  const disableGroupSelect = !loggedInUsersAccount || !loggedInUsersAccount.data || !loggedInUsersAccount.data.accountNumber;
27
28
  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
- }
29
+ const { data: groupUsers, loading: isFetching, fetchMembers } = useCaseGroupMembers();
30
+ // TODO: Uncomment when updateUsers is migrated to GraphQL
31
+ // function onPermissionError(error: Error, user: IGroupUser) {
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
+ // }
39
39
  // set and sort fetched data.
40
40
  const [initialData, setInitialData] = useState(groupUsers);
41
41
  const [data, setData] = useState(groupUsers);
42
- useEffect(() => setAllData(response || []), [response]);
42
+ useEffect(() => setAllData(groupUsers || []), [groupUsers]);
43
43
  function setAllData(users) {
44
44
  setInitialData(users);
45
45
  setData(users);
@@ -61,18 +61,19 @@ export const ManageGroupUsers = () => {
61
61
  const onGroupSelect = (group) => __awaiter(void 0, void 0, void 0, function* () {
62
62
  setSelectedGroup(group);
63
63
  if (group) {
64
- request(loggedInUsersAccount.data.accountNumber, group.groupNum);
64
+ fetchMembers(group.groupNum);
65
65
  }
66
66
  else {
67
- clearResponse();
67
+ setAllData([]);
68
68
  }
69
69
  });
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
- }
70
+ // TODO: Uncomment when updateUsers is migrated to GraphQL
71
+ // function onPermissionsChange(user: IGroupUser) {
72
+ // const initialUsers = initialData.map((value) => (value.ssoUsername === user.ssoUsername ? user : value));
73
+ // const users = data.map((value) => (value.ssoUsername === user.ssoUsername ? user : value));
74
+ // setInitialData(initialUsers);
75
+ // setData(users);
76
+ // }
76
77
  const columns = [
77
78
  {
78
79
  accessor: (user) => user.firstName,
@@ -92,11 +93,24 @@ export const ManageGroupUsers = () => {
92
93
  id: 'sso-username',
93
94
  title: t('Login'),
94
95
  },
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
- },
96
+ // TODO: Uncomment when updateUsers is migrated to GraphQL
97
+ // {
98
+ // id: 'permissions',
99
+ // title: t('Permissions'),
100
+ // cell: (user) =>
101
+ // user.isOrgAdmin ? (
102
+ // t('Admin/Full access')
103
+ // ) : (
104
+ // <GroupUserPermissionsSelect
105
+ // onChange={onPermissionsChange}
106
+ // account={loggedInUsersAccount.data}
107
+ // group={selectedGroup}
108
+ // users={data}
109
+ // user={user}
110
+ // onError={onPermissionError}
111
+ // />
112
+ // ),
113
+ // },
100
114
  {
101
115
  id: 'default',
102
116
  title: t('Default group'),
@@ -126,7 +140,7 @@ export const ManageGroupUsers = () => {
126
140
  if (location.pathname !== '/manage/groups') {
127
141
  return;
128
142
  }
129
- setAllData(response || []);
143
+ setAllData(groupUsers || []);
130
144
  // eslint-disable-next-line react-hooks/exhaustive-deps
131
145
  }, [location.pathname, loggedInUsersAccount.data]);
132
146
  return (React.createElement(React.Fragment, null,
@@ -140,5 +154,5 @@ export const ManageGroupUsers = () => {
140
154
  React.createElement(Trans, null, "Filter by")),
141
155
  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('') }))),
142
156
  React.createElement(ErrorBoundary, { errorMsgInfo: { message: t('There was an error loading group users list') } },
143
- React.createElement(ManageTable, { ariaLabel: t('Table to manage groups'), columns: columns, data: data, sortInfo: { column: 'first-name', direction: 'asc' }, isFetching: isFetching, isError: false }))));
157
+ 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 }))));
144
158
  };
@@ -1 +1 @@
1
- {"version":3,"file":"PreferencesACL.d.ts","sourceRoot":"","sources":["../../../../../src/components/ManagePreferences/sections/PreferencesACL.tsx"],"names":[],"mappings":"AASA,OAAO,KAA+B,MAAM,OAAO,CAAC;AAKpD,wBAAgB,cAAc,sBAwF7B"}
1
+ {"version":3,"file":"PreferencesACL.d.ts","sourceRoot":"","sources":["../../../../../src/components/ManagePreferences/sections/PreferencesACL.tsx"],"names":[],"mappings":"AAKA,OAAO,KAA+B,MAAM,OAAO,CAAC;AAKpD,wBAAgB,cAAc,sBAuF7B"}
@@ -11,15 +11,14 @@ import { accounts } from '@cee-eng/hydrajs';
11
11
  import { Card, CardBody, CardHeader, Spinner, Tooltip } from '@patternfly/react-core';
12
12
  import InfoCircleIcon from '@patternfly/react-icons/dist/js/icons/info-circle-icon';
13
13
  import { useFetch } from '@rh-support/components';
14
- import { fetchLoggedInUsersAccount, GlobalMetadataDispatchContext, GlobalMetadataStateContext, } from '@rh-support/react-context';
14
+ import { GlobalMetadataStateContext } from '@rh-support/react-context';
15
15
  import React, { useContext, useState } from 'react';
16
16
  import { Trans, useTranslation } from 'react-i18next';
17
17
  import { PreferenceSwitch } from '../components/PreferenceSwitch';
18
18
  export function PreferencesACL() {
19
19
  var _a;
20
20
  const { t } = useTranslation();
21
- const { globalMetadataState: { loggedInUsersAccount, loggedInUserJwtToken }, } = useContext(GlobalMetadataStateContext);
22
- const dispatchToGlobalMetadataReducer = useContext(GlobalMetadataDispatchContext);
21
+ const { globalMetadataState: { loggedInUsersAccount }, } = useContext(GlobalMetadataStateContext);
23
22
  const [isAclActivated, setIsAclActivated] = useState((_a = loggedInUsersAccount.data) === null || _a === void 0 ? void 0 : _a.hasGroupACLs);
24
23
  const [isAclLoading, setIsAclLoading] = useState(false);
25
24
  const { request: updateAcl } = useFetch(accounts.updateAcl);
@@ -27,7 +26,7 @@ export function PreferencesACL() {
27
26
  try {
28
27
  setIsAclLoading(true);
29
28
  yield updateAcl(!isAclActivated, loggedInUsersAccount.data.accountNumber);
30
- fetchLoggedInUsersAccount(dispatchToGlobalMetadataReducer, loggedInUserJwtToken, true);
29
+ // TODO: migrate to GraphQL - fetchLoggedInUsersAccount(dispatchToGlobalMetadataReducer, loggedInUserJwtToken, true, apolloClient);
31
30
  setIsAclActivated(!isAclActivated);
32
31
  }
33
32
  catch (error) {
@@ -1 +1 @@
1
- {"version":3,"file":"PreferencesCaseCreate.d.ts","sourceRoot":"","sources":["../../../../../src/components/ManagePreferences/sections/PreferencesCaseCreate.tsx"],"names":[],"mappings":"AAcA,OAAO,KAA0C,MAAM,OAAO,CAAC;AAO/D,UAAU,MAAM;CAAG;AACnB,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,qBA0MlD"}
1
+ {"version":3,"file":"PreferencesCaseCreate.d.ts","sourceRoot":"","sources":["../../../../../src/components/ManagePreferences/sections/PreferencesCaseCreate.tsx"],"names":[],"mappings":"AAeA,OAAO,KAA0C,MAAM,OAAO,CAAC;AAO/D,UAAU,MAAM;CAAG;AACnB,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,qBA2MlD"}
@@ -7,6 +7,7 @@ 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 { useApolloClient } from '@apollo/client/react';
10
11
  import { publicApi } from '@cee-eng/hydrajs';
11
12
  import { Card, CardBody, CardHeader, SelectOption } from '@patternfly/react-core';
12
13
  import { ToastNotification, useFetch } from '@rh-support/components';
@@ -22,6 +23,7 @@ import { PreferenceSelect } from '../components/PreferenceSelect';
22
23
  export function PreferencesCaseCreate(props) {
23
24
  const { t } = useTranslation();
24
25
  const location = useLocation();
26
+ const apolloClient = useApolloClient();
25
27
  const { globalMetadataState: { caseGroups, caseLanguages, loggedInUserJwtToken, loggedInUserRights, loggedInUsersAccount, }, } = useContext(GlobalMetadataStateContext);
26
28
  const dispatchToGlobalMetadataReducer = useContext(GlobalMetadataDispatchContext);
27
29
  const languageConst = caseLanguages.data;
@@ -136,10 +138,10 @@ export function PreferencesCaseCreate(props) {
136
138
  }, [location.pathname]);
137
139
  useEffect(() => {
138
140
  if (haventLoadedMetadata(caseLanguages)) {
139
- fetchLanguageMetadata(dispatchToGlobalMetadataReducer);
141
+ fetchLanguageMetadata(dispatchToGlobalMetadataReducer, apolloClient);
140
142
  }
141
143
  // eslint-disable-next-line react-hooks/exhaustive-deps
142
- }, [caseLanguages]);
144
+ }, [caseLanguages, apolloClient]);
143
145
  return (React.createElement(Card, { variant: "secondary", className: "preference-card" },
144
146
  React.createElement(CardHeader, null,
145
147
  React.createElement("h3", null,
@@ -1 +1 @@
1
- {"version":3,"file":"PreferencesCaseView.d.ts","sourceRoot":"","sources":["../../../../../src/components/ManagePreferences/sections/PreferencesCaseView.tsx"],"names":[],"mappings":"AAsBA,OAAO,KAA0C,MAAM,OAAO,CAAC;AAO/D,UAAU,MAAM;CAAG;AAEnB,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,qBAqShD"}
1
+ {"version":3,"file":"PreferencesCaseView.d.ts","sourceRoot":"","sources":["../../../../../src/components/ManagePreferences/sections/PreferencesCaseView.tsx"],"names":[],"mappings":"AAkBA,OAAO,KAA0C,MAAM,OAAO,CAAC;AAO/D,UAAU,MAAM;CAAG;AAEnB,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,qBAmShD"}
@@ -11,7 +11,7 @@ import { accounts } from '@cee-eng/hydrajs';
11
11
  import { Card, CardBody, CardHeader, Popover, PopoverPosition, SelectOption, Spinner, TextArea, Tooltip, } from '@patternfly/react-core';
12
12
  import InfoCircleIcon from '@patternfly/react-icons/dist/js/icons/info-circle-icon';
13
13
  import { EditorMode, ToastNotification, useFetch } from '@rh-support/components';
14
- import { fetchLoggedInUsersAccount, GlobalMetadataDispatchContext, GlobalMetadataStateContext, } from '@rh-support/react-context';
14
+ import { GlobalMetadataStateContext } from '@rh-support/react-context';
15
15
  import { ability, CaseListFields, resourceActions, resources } from '@rh-support/user-permissions';
16
16
  import debounce from 'lodash/debounce';
17
17
  import isEmpty from 'lodash/isEmpty';
@@ -23,8 +23,7 @@ import { PreferenceSwitch } from '../components/PreferenceSwitch';
23
23
  export function PreferencesCaseView(props) {
24
24
  const { t } = useTranslation();
25
25
  const { updateCommentType, getCommentTypeFromPreference, getCommentSignature, updateCommentSignature, getOriginalCaseView, updateOriginalCaseView, } = useUserPreferences();
26
- const { globalMetadataState: { loggedInUsersAccount, loggedInUserJwtToken, loggedInUserRights }, } = useContext(GlobalMetadataStateContext);
27
- const dispatchToGlobalMetadataReducer = useContext(GlobalMetadataDispatchContext);
26
+ const { globalMetadataState: { loggedInUsersAccount, loggedInUserRights }, } = useContext(GlobalMetadataStateContext);
28
27
  const [isSharingHostNames, setIsSharingHostNames] = useState(false);
29
28
  const [localCommentSignature, setLocalCommentSignature] = useState('');
30
29
  const [originalCommentType, setOriginalCommentType] = useState('');
@@ -170,7 +169,7 @@ export function PreferencesCaseView(props) {
170
169
  try {
171
170
  setIsHostnamesLoading(true);
172
171
  yield updateShareHostnames(!isSharingHostNames, accountNumber);
173
- fetchLoggedInUsersAccount(dispatchToGlobalMetadataReducer, loggedInUserJwtToken, true);
172
+ // TODO: migrate to GraphQL - fetchLoggedInUsersAccount(dispatchToGlobalMetadataReducer, loggedInUserJwtToken, true, apolloClient);
174
173
  setIsSharingHostNames(!isSharingHostNames);
175
174
  }
176
175
  catch (error) {
@@ -0,0 +1,32 @@
1
+ import { type CreateCaseGroupResponse, type DeleteCaseGroupResponse, type RenameCaseGroupResponse, type ToggleDefaultGroupResponse } from '@rh-support/utils';
2
+ import { type IGroupUserWithContactId } from '../utils/caseGroupMapper';
3
+ interface UseCaseGroupMembersResult {
4
+ data: IGroupUserWithContactId[];
5
+ loading: boolean;
6
+ error: Error | undefined;
7
+ refetch: () => void;
8
+ fetchMembers: (groupId: string) => void;
9
+ }
10
+ export declare function useCaseGroupMembers(): UseCaseGroupMembersResult;
11
+ interface UseCreateCaseGroupResult {
12
+ createGroup: (name: string, accountId: string) => Promise<CreateCaseGroupResponse>;
13
+ loading: boolean;
14
+ }
15
+ export declare function useCreateCaseGroup(): UseCreateCaseGroupResult;
16
+ interface UseRenameCaseGroupResult {
17
+ renameGroup: (id: string, newName: string) => Promise<RenameCaseGroupResponse>;
18
+ loading: boolean;
19
+ }
20
+ export declare function useRenameCaseGroup(): UseRenameCaseGroupResult;
21
+ interface UseDeleteCaseGroupResult {
22
+ deleteGroup: (id: string) => Promise<DeleteCaseGroupResponse>;
23
+ loading: boolean;
24
+ }
25
+ export declare function useDeleteCaseGroup(): UseDeleteCaseGroupResult;
26
+ interface UseToggleDefaultGroupResult {
27
+ toggleDefault: (contactId: string, groupId: string | null) => Promise<ToggleDefaultGroupResponse>;
28
+ loading: boolean;
29
+ }
30
+ export declare function useToggleDefaultGroup(): UseToggleDefaultGroupResult;
31
+ export {};
32
+ //# sourceMappingURL=useCaseGroupGraphQL.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useCaseGroupGraphQL.d.ts","sourceRoot":"","sources":["../../../src/hooks/useCaseGroupGraphQL.ts"],"names":[],"mappings":"AACA,OAAO,EACH,KAAK,uBAAuB,EAC5B,KAAK,uBAAuB,EAG5B,KAAK,uBAAuB,EAC5B,KAAK,0BAA0B,EAMlC,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAE,KAAK,uBAAuB,EAAsC,MAAM,0BAA0B,CAAC;AAE5G,UAAU,yBAAyB;IAC/B,IAAI,EAAE,uBAAuB,EAAE,CAAC;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,KAAK,GAAG,SAAS,CAAC;IACzB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,YAAY,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3C;AAED,wBAAgB,mBAAmB,IAAI,yBAAyB,CAqC/D;AAED,UAAU,wBAAwB;IAC9B,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,uBAAuB,CAAC,CAAC;IACnF,OAAO,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,kBAAkB,IAAI,wBAAwB,CAW7D;AAED,UAAU,wBAAwB;IAC9B,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,uBAAuB,CAAC,CAAC;IAC/E,OAAO,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,kBAAkB,IAAI,wBAAwB,CAW7D;AAED,UAAU,wBAAwB;IAC9B,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,uBAAuB,CAAC,CAAC;IAC9D,OAAO,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,kBAAkB,IAAI,wBAAwB,CAW7D;AAED,UAAU,2BAA2B;IACjC,aAAa,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,KAAK,OAAO,CAAC,0BAA0B,CAAC,CAAC;IAClG,OAAO,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,qBAAqB,IAAI,2BAA2B,CAcnE"}
@@ -0,0 +1,94 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { useApolloClient, useMutation } from '@apollo/client/react';
11
+ import { CREATE_CASE_GROUP, DELETE_CASE_GROUP, GET_CASE_GROUP_MEMBERS, RENAME_CASE_GROUP, TOGGLE_DEFAULT_GROUP, } from '@rh-support/utils';
12
+ import { useState } from 'react';
13
+ import { mapCaseGroupMemberNodeToIGroupUser } from '../utils/caseGroupMapper';
14
+ export function useCaseGroupMembers() {
15
+ const client = useApolloClient();
16
+ const [members, setMembers] = useState([]);
17
+ const [loading, setLoading] = useState(false);
18
+ const [error, setError] = useState(undefined);
19
+ const [currentGroupId, setCurrentGroupId] = useState(undefined);
20
+ const fetchMembers = (groupId) => __awaiter(this, void 0, void 0, function* () {
21
+ var _a, _b, _c;
22
+ setCurrentGroupId(groupId);
23
+ setLoading(true);
24
+ setError(undefined);
25
+ try {
26
+ const { data } = yield client.query({
27
+ query: GET_CASE_GROUP_MEMBERS,
28
+ variables: { where: { Group__c: { eq: groupId } } },
29
+ fetchPolicy: 'network-only',
30
+ });
31
+ const edges = ((_c = (_b = (_a = data === null || data === void 0 ? void 0 : data.redhat_support_uiapi) === null || _a === void 0 ? void 0 : _a.query) === null || _b === void 0 ? void 0 : _b.RedHatSupportCaseGroupMember__c) === null || _c === void 0 ? void 0 : _c.edges) || [];
32
+ const mapped = edges
33
+ .filter(({ node }) => node.Contact__r !== null)
34
+ .map(({ node }) => mapCaseGroupMemberNodeToIGroupUser(node, groupId));
35
+ setMembers(mapped);
36
+ }
37
+ catch (e) {
38
+ setError(e);
39
+ setMembers([]);
40
+ }
41
+ finally {
42
+ setLoading(false);
43
+ }
44
+ });
45
+ const refetch = () => {
46
+ if (currentGroupId) {
47
+ fetchMembers(currentGroupId);
48
+ }
49
+ };
50
+ return { data: members, loading, error, refetch, fetchMembers };
51
+ }
52
+ export function useCreateCaseGroup() {
53
+ const [mutate, { loading }] = useMutation(CREATE_CASE_GROUP);
54
+ const createGroup = (name, accountId) => __awaiter(this, void 0, void 0, function* () {
55
+ const result = yield mutate({
56
+ variables: { name, accountId },
57
+ });
58
+ return result.data;
59
+ });
60
+ return { createGroup, loading };
61
+ }
62
+ export function useRenameCaseGroup() {
63
+ const [mutate, { loading }] = useMutation(RENAME_CASE_GROUP);
64
+ const renameGroup = (id, newName) => __awaiter(this, void 0, void 0, function* () {
65
+ const result = yield mutate({
66
+ variables: { id, caseGroupPatch: { Name: newName } },
67
+ });
68
+ return result.data;
69
+ });
70
+ return { renameGroup, loading };
71
+ }
72
+ export function useDeleteCaseGroup() {
73
+ const [mutate, { loading }] = useMutation(DELETE_CASE_GROUP);
74
+ const deleteGroup = (id) => __awaiter(this, void 0, void 0, function* () {
75
+ const result = yield mutate({
76
+ variables: { id },
77
+ });
78
+ return result.data;
79
+ });
80
+ return { deleteGroup, loading };
81
+ }
82
+ export function useToggleDefaultGroup() {
83
+ const [mutate, { loading }] = useMutation(TOGGLE_DEFAULT_GROUP);
84
+ const toggleDefault = (contactId, groupId) => __awaiter(this, void 0, void 0, function* () {
85
+ const result = yield mutate({
86
+ variables: {
87
+ id: contactId,
88
+ contactPatch: { DefaultCaseGroup__c: groupId },
89
+ },
90
+ });
91
+ return result.data;
92
+ });
93
+ return { toggleDefault, loading };
94
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"useVersionsDiffer.d.ts","sourceRoot":"","sources":["../../../src/hooks/useVersionsDiffer.tsx"],"names":[],"mappings":"AAOA;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,GAAI,qBAAqB,MAAM,EAAE,sBAAsB,MAAM,KAAG,CAAC,OAAO,EAAE,MAAM,EAAE,CAuD/G,CAAC"}
1
+ {"version":3,"file":"useVersionsDiffer.d.ts","sourceRoot":"","sources":["../../../src/hooks/useVersionsDiffer.tsx"],"names":[],"mappings":"AAOA;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,GAAI,qBAAqB,MAAM,EAAE,sBAAsB,MAAM,KAAG,CAAC,OAAO,EAAE,MAAM,EAAE,CAwD/G,CAAC"}
@@ -179,6 +179,7 @@
179
179
  border-radius: 8px;
180
180
  border-top-right-radius: 0px;
181
181
  border-top-left-radius: 0px;
182
+ overflow: hidden;
182
183
 
183
184
  .pf-v6-c-table__th {
184
185
  font-size: 14px;
@@ -194,6 +195,10 @@
194
195
  tbody:first-of-type {
195
196
  border-top: none;
196
197
  }
198
+
199
+ tbody:last-of-type tr:last-child {
200
+ border-bottom: none;
201
+ }
197
202
  .bookmark-alert {
198
203
  margin-left: 1rem;
199
204
  margin-right: 1rem;
@@ -0,0 +1,17 @@
1
+ import type { ICaseGroup, IGroupUser } from '@cee-eng/hydrajs/@types/api/public/caseGroups';
2
+ import type { CaseGroupMemberNode, CaseGroupNode } from '@rh-support/utils';
3
+ /** Extends the hydrajs IGroupUser with the Salesforce Contact record Id needed for mutations like ContactUpdate. */
4
+ export interface IGroupUserWithContactId extends IGroupUser {
5
+ contactSfId: string;
6
+ }
7
+ /**
8
+ * Maps a Salesforce GraphQL CaseGroupNode to the legacy ICaseGroup shape
9
+ * used throughout the application.
10
+ */
11
+ export declare function mapCaseGroupNodeToICaseGroup(node: CaseGroupNode, isDefault?: boolean): ICaseGroup;
12
+ /**
13
+ * Maps a Salesforce GraphQL CaseGroupMemberNode to the legacy IGroupUser shape.
14
+ * Derives `isDefault` by comparing the contact's DefaultCaseGroup__c against the current group Id.
15
+ */
16
+ export declare function mapCaseGroupMemberNodeToIGroupUser(node: CaseGroupMemberNode, groupId: string): IGroupUserWithContactId;
17
+ //# sourceMappingURL=caseGroupMapper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"caseGroupMapper.d.ts","sourceRoot":"","sources":["../../../src/utils/caseGroupMapper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,+CAA+C,CAAC;AAC5F,OAAO,KAAK,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAE5E,oHAAoH;AACpH,MAAM,WAAW,uBAAwB,SAAQ,UAAU;IACvD,WAAW,EAAE,MAAM,CAAC;CACvB;AAED;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,aAAa,EAAE,SAAS,UAAQ,GAAG,UAAU,CAS/F;AAED;;;GAGG;AACH,wBAAgB,kCAAkC,CAC9C,IAAI,EAAE,mBAAmB,EACzB,OAAO,EAAE,MAAM,GAChB,uBAAuB,CA2BzB"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Maps a Salesforce GraphQL CaseGroupNode to the legacy ICaseGroup shape
3
+ * used throughout the application.
4
+ */
5
+ export function mapCaseGroupNodeToICaseGroup(node, isDefault = false) {
6
+ var _a;
7
+ return {
8
+ groupNum: node.Id,
9
+ name: (_a = node.Name.displayValue) !== null && _a !== void 0 ? _a : node.Name.value,
10
+ isPrivate: false,
11
+ isDefault,
12
+ defaultMembers: [],
13
+ members: [],
14
+ };
15
+ }
16
+ /**
17
+ * Maps a Salesforce GraphQL CaseGroupMemberNode to the legacy IGroupUser shape.
18
+ * Derives `isDefault` by comparing the contact's DefaultCaseGroup__c against the current group Id.
19
+ */
20
+ export function mapCaseGroupMemberNodeToIGroupUser(node, groupId) {
21
+ var _a, _b, _c, _d;
22
+ const contact = node.Contact__r;
23
+ if (!contact) {
24
+ return {
25
+ firstName: '',
26
+ lastName: '',
27
+ isOrgAdmin: false,
28
+ access: true,
29
+ write: false,
30
+ isDefault: false,
31
+ ssoUsername: '',
32
+ email: '',
33
+ contactSfId: '',
34
+ };
35
+ }
36
+ return {
37
+ firstName: (_a = contact.FirstName.displayValue) !== null && _a !== void 0 ? _a : contact.FirstName.value,
38
+ lastName: (_b = contact.LastName.displayValue) !== null && _b !== void 0 ? _b : contact.LastName.value,
39
+ isOrgAdmin: contact.IsOrgAdmin__c.value,
40
+ access: true,
41
+ write: false,
42
+ isDefault: ((_c = contact.DefaultCaseGroup__c) === null || _c === void 0 ? void 0 : _c.value) === groupId,
43
+ ssoUsername: contact.SSOUserName__c.value,
44
+ email: (_d = contact.Email.displayValue) !== null && _d !== void 0 ? _d : contact.Email.value,
45
+ contactSfId: contact.Id,
46
+ };
47
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rh-support/manage",
3
- "version": "2.5.230",
3
+ "version": "2.5.232",
4
4
  "description": "Customer Support Manage App",
5
5
  "author": "Jordan Eudy <jeudy100@gmail.com>",
6
6
  "license": "ISC",
@@ -41,7 +41,8 @@
41
41
  "prepublishOnly": "npm run build"
42
42
  },
43
43
  "peerDependencies": {
44
- "@cee-eng/hydrajs": "4.18.111",
44
+ "@apollo/client": "^4.1.6",
45
+ "@cee-eng/hydrajs": "^4.18.113",
45
46
  "@patternfly/patternfly": "6.2.1",
46
47
  "@patternfly/react-core": "6.2.1",
47
48
  "@patternfly/react-table": "6.2.1",
@@ -71,16 +72,16 @@
71
72
  "typescript": "^5.3.3"
72
73
  },
73
74
  "dependencies": {
74
- "@cee-eng/hydrajs": "4.18.111",
75
+ "@cee-eng/hydrajs": "^4.18.113",
75
76
  "@patternfly/patternfly": "6.2.1",
76
77
  "@patternfly/react-core": "6.2.1",
77
78
  "@patternfly/react-table": "6.2.1",
78
- "@rh-support/components": "2.5.182",
79
+ "@rh-support/components": "2.5.184",
79
80
  "@rh-support/configs": "2.0.75",
80
- "@rh-support/react-context": "2.5.276",
81
+ "@rh-support/react-context": "2.5.278",
81
82
  "@rh-support/types": "2.0.26",
82
- "@rh-support/user-permissions": "2.5.128",
83
- "@rh-support/utils": "2.5.92",
83
+ "@rh-support/user-permissions": "2.5.130",
84
+ "@rh-support/utils": "2.5.112",
84
85
  "@types/react-beautiful-dnd": "^13.0.0",
85
86
  "i18next": "^23.15.0",
86
87
  "lodash": ">=4.17.15",
@@ -99,5 +100,5 @@
99
100
  "defaults and supports es6-module",
100
101
  "maintained node versions"
101
102
  ],
102
- "gitHead": "ab00ab0180e7ed16e1d170328e568a0aba4599c3"
103
+ "gitHead": "d93a57f2a62bdfc7ec25341b3dcae197f3e5f1a3"
103
104
  }