@rh-support/manage 2.5.235 → 2.5.238
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/esm/ManageTabs.d.ts.map +1 -1
- package/lib/esm/ManageTabs.js +17 -2
- package/lib/esm/Routes.d.ts +1 -0
- package/lib/esm/Routes.d.ts.map +1 -1
- package/lib/esm/Routes.js +6 -0
- package/lib/esm/components/Groups/AddMembersModal/AddMembersModal.d.ts +12 -0
- package/lib/esm/components/Groups/AddMembersModal/AddMembersModal.d.ts.map +1 -0
- package/lib/esm/components/Groups/AddMembersModal/AddMembersModal.js +81 -0
- package/lib/esm/components/Groups/AddMembersModal/index.d.ts +2 -0
- package/lib/esm/components/Groups/AddMembersModal/index.d.ts.map +1 -0
- package/lib/esm/components/Groups/AddMembersModal/index.js +1 -0
- package/lib/esm/components/Groups/GroupSelect/GroupSelect.d.ts +1 -0
- package/lib/esm/components/Groups/GroupSelect/GroupSelect.d.ts.map +1 -1
- package/lib/esm/components/Groups/GroupSelect/GroupSelect.js +7 -0
- package/lib/esm/components/Groups/ManageGroupUsers/ManageGroupUsers.d.ts.map +1 -1
- package/lib/esm/components/Groups/ManageGroupUsers/ManageGroupUsers.js +17 -8
- package/lib/esm/components/ManageCaseLabels/AddEditCaseLabelModal.d.ts +19 -0
- package/lib/esm/components/ManageCaseLabels/AddEditCaseLabelModal.d.ts.map +1 -0
- package/lib/esm/components/ManageCaseLabels/AddEditCaseLabelModal.js +72 -0
- package/lib/esm/components/ManageCaseLabels/ManageCaseLabelsTab.d.ts +3 -0
- package/lib/esm/components/ManageCaseLabels/ManageCaseLabelsTab.d.ts.map +1 -0
- package/lib/esm/components/ManageCaseLabels/ManageCaseLabelsTab.js +199 -0
- package/lib/esm/components/ManageCaseLabels/index.d.ts +2 -0
- package/lib/esm/components/ManageCaseLabels/index.d.ts.map +1 -0
- package/lib/esm/components/ManageCaseLabels/index.js +1 -0
- package/lib/esm/components/ManageCaseLabels/types.d.ts +6 -0
- package/lib/esm/components/ManageCaseLabels/types.d.ts.map +1 -0
- package/lib/esm/components/ManageCaseLabels/types.js +1 -0
- package/lib/esm/components/ManagePreferences/sections/PreferencesCaseCreate.d.ts.map +1 -1
- package/lib/esm/components/ManagePreferences/sections/PreferencesCaseCreate.js +20 -41
- package/lib/esm/constants/GroupSelectActions.d.ts +2 -1
- package/lib/esm/constants/GroupSelectActions.d.ts.map +1 -1
- package/lib/esm/constants/GroupSelectActions.js +1 -0
- package/lib/esm/hooks/useCaseGroupGraphQL.d.ts +6 -1
- package/lib/esm/hooks/useCaseGroupGraphQL.d.ts.map +1 -1
- package/lib/esm/hooks/useCaseGroupGraphQL.js +42 -37
- package/lib/esm/hooks/useCaseLabelGraphQL.d.ts +26 -0
- package/lib/esm/hooks/useCaseLabelGraphQL.d.ts.map +1 -0
- package/lib/esm/hooks/useCaseLabelGraphQL.js +99 -0
- package/lib/esm/hooks/useCurrentUserContact.d.ts +8 -0
- package/lib/esm/hooks/useCurrentUserContact.d.ts.map +1 -0
- package/lib/esm/hooks/useCurrentUserContact.js +74 -0
- package/lib/esm/scss/_main.scss +63 -0
- package/package.json +6 -6
|
@@ -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;
|
|
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;AAiBlE,UAAU,MAAM;IACZ,UAAU,EAAE,mBAAmB,CAAC,EAAE,CAAC,CAAC;IACpC,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,qBAgOvC"}
|
package/lib/esm/ManageTabs.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Tab, TabContent, Tabs, TabsComponent, TabTitleText } from '@patternfly/react-core';
|
|
2
|
-
import { ErrorBoundary, useDocumentTitle } from '@rh-support/components';
|
|
2
|
+
import { ErrorBoundary, LoadingIndicator, useDocumentTitle } from '@rh-support/components';
|
|
3
3
|
import { ability, resourceActions, resources } from '@rh-support/user-permissions';
|
|
4
4
|
import map from 'lodash/map';
|
|
5
5
|
import React, { useState } from 'react';
|
|
@@ -8,6 +8,7 @@ import { useParams } from 'react-router-dom';
|
|
|
8
8
|
import { ConfigsTable } from './components/Configs/ConfigsTable';
|
|
9
9
|
import { ManageGroupUsers } from './components/Groups/ManageGroupUsers';
|
|
10
10
|
import { ManageGroupedBookmarkedAccountsTab } from './components/ManageBookmarkedAccountsTab';
|
|
11
|
+
import { ManageCaseLabelsTab } from './components/ManageCaseLabels';
|
|
11
12
|
import { ExpiredContentManagement } from './components/ManageExpiredContents/ExpiredContentManagement';
|
|
12
13
|
// TODO: Uncomment when partnerships tab is re-implemented
|
|
13
14
|
// import { ManagePartnerships } from './components/ManagePartnerships/index';
|
|
@@ -16,13 +17,15 @@ import { TagsManagement } from './components/ManageTags';
|
|
|
16
17
|
// import { NotificationEmails } from './components/NotificationEmails/index';
|
|
17
18
|
import { TopContentManagement } from './components/TopContentManagement';
|
|
18
19
|
import { PageTitle } from './constants/pageTitle';
|
|
20
|
+
import { useCurrentUserContact } from './hooks/useCurrentUserContact';
|
|
19
21
|
import { Routes } from './Routes';
|
|
20
22
|
export function ManageTabs(props) {
|
|
21
23
|
var _a, _b;
|
|
22
24
|
const [activeTabKey, setActiveTabKey] = useState(0);
|
|
23
25
|
const { activeTab } = useParams();
|
|
24
26
|
const { t } = useTranslation();
|
|
25
|
-
const {
|
|
27
|
+
const { loading: contactLoading } = useCurrentUserContact();
|
|
28
|
+
const { groupsRoute, bookmarkedAccountsRoute, caseLabelsRoute, topContentRoute,
|
|
26
29
|
// notificationEmailsRoute,
|
|
27
30
|
preferencesRoute, configsRoute,
|
|
28
31
|
// partnershipsRoute, // TODO: Uncomment when partnerships tab is re-implemented
|
|
@@ -41,6 +44,10 @@ export function ManageTabs(props) {
|
|
|
41
44
|
// CaseDetailsFields.CASE_DETAILS_SEND_NOTIFICATIONS
|
|
42
45
|
// );
|
|
43
46
|
const canViewConfigsTab = ability.can(resourceActions.READ, resources.APP_INTERNAL_CONFIGS);
|
|
47
|
+
if (contactLoading) {
|
|
48
|
+
return (React.createElement("div", { className: "grid-main manage" },
|
|
49
|
+
React.createElement(LoadingIndicator, { show: true, size: "sm" })));
|
|
50
|
+
}
|
|
44
51
|
const tabsToRender = [];
|
|
45
52
|
canManageBookmarkAccounts &&
|
|
46
53
|
tabsToRender.push({
|
|
@@ -60,6 +67,14 @@ export function ManageTabs(props) {
|
|
|
60
67
|
component: React.createElement(ManageGroupUsers, null),
|
|
61
68
|
id: 'manage-groups',
|
|
62
69
|
});
|
|
70
|
+
tabsToRender.push({
|
|
71
|
+
title: 'Case labels',
|
|
72
|
+
key: 'case-labels-tab',
|
|
73
|
+
'data-tracking-id': 'manage-case-labels-tab',
|
|
74
|
+
routePath: caseLabelsRoute,
|
|
75
|
+
component: React.createElement(ManageCaseLabelsTab, null),
|
|
76
|
+
id: 'manage-case-labels',
|
|
77
|
+
});
|
|
63
78
|
/* TODO: Re-enable notification emails tab when ready
|
|
64
79
|
canViewEmailNotificationTab &&
|
|
65
80
|
canAddCustomNotification &&
|
package/lib/esm/Routes.d.ts
CHANGED
package/lib/esm/Routes.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Routes.d.ts","sourceRoot":"","sources":["../../src/Routes.ts"],"names":[],"mappings":"AAAA,UAAU,KAAK;IACX,QAAQ,CAAC,OAAO,EAAE,MAAM,MAAM,CAAC;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACzB;AAED,UAAU,YAAY;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,kBAAkB,EAAE,KAAK,CAAC;IAC1B,eAAe,EAAE,KAAK,CAAC;IACvB,QAAQ,EAAE,MAAM;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IAC1C,aAAa,EAAE,MAAM,MAAM,EAAE,CAAC;IAC9B,MAAM,EAAE,KAAK,CAAC;IACd,aAAa,EAAE,KAAK,CAAC;IACrB,UAAU,EAAE,KAAK,CAAC;IAClB,cAAc,EAAE,KAAK,CAAC;IACtB,WAAW,EAAE,KAAK,CAAC;IACnB,WAAW,EAAE,KAAK,CAAC;IACnB,kBAAkB,EAAE,KAAK,CAAC;IAC1B,OAAO,EAAE,KAAK,CAAC;IACf,YAAY,EAAE,KAAK,CAAC;CACvB;AAED,eAAO,MAAM,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"Routes.d.ts","sourceRoot":"","sources":["../../src/Routes.ts"],"names":[],"mappings":"AAAA,UAAU,KAAK;IACX,QAAQ,CAAC,OAAO,EAAE,MAAM,MAAM,CAAC;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACzB;AAED,UAAU,YAAY;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,kBAAkB,EAAE,KAAK,CAAC;IAC1B,eAAe,EAAE,KAAK,CAAC;IACvB,QAAQ,EAAE,MAAM;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IAC1C,aAAa,EAAE,MAAM,MAAM,EAAE,CAAC;IAC9B,MAAM,EAAE,KAAK,CAAC;IACd,UAAU,EAAE,KAAK,CAAC;IAClB,aAAa,EAAE,KAAK,CAAC;IACrB,UAAU,EAAE,KAAK,CAAC;IAClB,cAAc,EAAE,KAAK,CAAC;IACtB,WAAW,EAAE,KAAK,CAAC;IACnB,WAAW,EAAE,KAAK,CAAC;IACnB,kBAAkB,EAAE,KAAK,CAAC;IAC1B,OAAO,EAAE,KAAK,CAAC;IACf,YAAY,EAAE,KAAK,CAAC;CACvB;AAED,eAAO,MAAM,MAAM,EAAE,YA2FpB,CAAC"}
|
package/lib/esm/Routes.js
CHANGED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ICaseGroup } from '@cee-eng/hydrajs/@types/api/public/caseGroups';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import type { IGroupUserWithContactId } from '../../../utils/caseGroupMapper';
|
|
4
|
+
interface IProps {
|
|
5
|
+
readonly group: ICaseGroup;
|
|
6
|
+
readonly existingMembers: IGroupUserWithContactId[];
|
|
7
|
+
readonly onSuccess: () => void;
|
|
8
|
+
readonly onClose: () => void;
|
|
9
|
+
}
|
|
10
|
+
export declare function AddMembersModal({ group, existingMembers, onSuccess, onClose }: IProps): React.JSX.Element;
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=AddMembersModal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AddMembersModal.d.ts","sourceRoot":"","sources":["../../../../../src/components/Groups/AddMembersModal/AddMembersModal.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,+CAA+C,CAAC;AAM3E,OAAO,KAAgC,MAAM,OAAO,CAAC;AAIrD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AAE9E,UAAU,MAAM;IACZ,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,QAAQ,CAAC,eAAe,EAAE,uBAAuB,EAAE,CAAC;IACpD,QAAQ,CAAC,SAAS,EAAE,MAAM,IAAI,CAAC;IAC/B,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC;CAChC;AAED,wBAAgB,eAAe,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,MAAM,qBAyGrF"}
|
|
@@ -0,0 +1,81 @@
|
|
|
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 { Button, Modal, ModalBody, ModalFooter, ModalHeader, ModalVariant } from '@patternfly/react-core';
|
|
11
|
+
import { CaseContactsSelectorExternal, ToastNotification } from '@rh-support/components';
|
|
12
|
+
import { useGlobalStateContext } from '@rh-support/react-context';
|
|
13
|
+
import React, { useCallback, useState } from 'react';
|
|
14
|
+
import { useTranslation } from 'react-i18next';
|
|
15
|
+
import { useCreateCaseGroupMember } from '../../../hooks/useCaseGroupGraphQL';
|
|
16
|
+
export function AddMembersModal({ group, existingMembers, onSuccess, onClose }) {
|
|
17
|
+
var _a, _b;
|
|
18
|
+
const { t } = useTranslation();
|
|
19
|
+
const { globalMetadataState: { loggedInUserRights, loggedInUsersAccount }, } = useGlobalStateContext();
|
|
20
|
+
const { createMember, loading: createLoading } = useCreateCaseGroupMember();
|
|
21
|
+
const [selectedContacts, setSelectedContacts] = useState([]);
|
|
22
|
+
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
23
|
+
const accountNumber = (_b = (_a = loggedInUsersAccount === null || loggedInUsersAccount === void 0 ? void 0 : loggedInUsersAccount.data) === null || _a === void 0 ? void 0 : _a.accountNumber) !== null && _b !== void 0 ? _b : '';
|
|
24
|
+
const contactSsoUsername = '';
|
|
25
|
+
const contactsToExclude = existingMembers.map((m) => ({
|
|
26
|
+
ssoUsername: m.ssoUsername,
|
|
27
|
+
firstName: m.firstName,
|
|
28
|
+
lastName: m.lastName,
|
|
29
|
+
}));
|
|
30
|
+
const contactFilter = useCallback((contact) => !contact.isOrgAdmin, []);
|
|
31
|
+
const onChange = useCallback((contacts) => {
|
|
32
|
+
if (!(contacts === null || contacts === void 0 ? void 0 : contacts.length))
|
|
33
|
+
return;
|
|
34
|
+
const contact = contacts[0];
|
|
35
|
+
if (!('ssoUsername' in contact))
|
|
36
|
+
return;
|
|
37
|
+
setSelectedContacts((prev) => {
|
|
38
|
+
const exists = prev.some((c) => c.ssoUsername === contact.ssoUsername);
|
|
39
|
+
return exists ? prev.filter((c) => c.ssoUsername !== contact.ssoUsername) : [...prev, contact];
|
|
40
|
+
});
|
|
41
|
+
}, []);
|
|
42
|
+
const onSubmit = () => __awaiter(this, void 0, void 0, function* () {
|
|
43
|
+
const validContacts = selectedContacts.filter((contact) => contact.id);
|
|
44
|
+
if (validContacts.length === 0)
|
|
45
|
+
return;
|
|
46
|
+
setIsSubmitting(true);
|
|
47
|
+
try {
|
|
48
|
+
const results = yield Promise.allSettled(validContacts.map((contact) => createMember(contact.id, group.groupNum)));
|
|
49
|
+
const succeeded = results.filter((r) => r.status === 'fulfilled');
|
|
50
|
+
const failed = results.filter((r) => r.status === 'rejected');
|
|
51
|
+
if (succeeded.length > 0) {
|
|
52
|
+
ToastNotification.addSuccessMessage(t('{{count}} people have been successfully added.', { count: succeeded.length }));
|
|
53
|
+
onSuccess();
|
|
54
|
+
}
|
|
55
|
+
if (failed.length > 0) {
|
|
56
|
+
const firstError = failed[0].reason;
|
|
57
|
+
const message = String((firstError === null || firstError === void 0 ? void 0 : firstError.message) || '');
|
|
58
|
+
if (message.includes('Organization Administrator')) {
|
|
59
|
+
ToastNotification.addDangerMessage(t('Organization Administrators cannot be added as case group members'));
|
|
60
|
+
}
|
|
61
|
+
else if (message.includes('insufficient access rights')) {
|
|
62
|
+
ToastNotification.addDangerMessage(t('You do not have permission to add members to this group'));
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
ToastNotification.addDangerMessage(t('There was an error adding members to this group'));
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
onClose();
|
|
69
|
+
}
|
|
70
|
+
finally {
|
|
71
|
+
setIsSubmitting(false);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
return (React.createElement(Modal, { variant: ModalVariant.medium, isOpen: true, onClose: onClose, "aria-label": t('Add members to group') },
|
|
75
|
+
React.createElement(ModalHeader, { title: t('Add members to {{groupName}}', { groupName: group.name }) }),
|
|
76
|
+
React.createElement(ModalBody, null,
|
|
77
|
+
React.createElement(CaseContactsSelectorExternal, { id: "add-members-contact-select", selectedAccountNumber: accountNumber, loggedInUserRights: loggedInUserRights.data, contactSsoUsername: contactSsoUsername, contactsToExclude: [...contactsToExclude, ...selectedContacts], contactFilter: contactFilter, selected: selectedContacts, onChange: onChange, onContactEnriched: () => { }, multiple: true, clearButton: true, isDisabled: isSubmitting, placeholder: t('Search by name or SSO username') })),
|
|
78
|
+
React.createElement(ModalFooter, null,
|
|
79
|
+
React.createElement(Button, { key: "confirm", variant: "primary", onClick: onSubmit, isDisabled: selectedContacts.length === 0 || isSubmitting || createLoading, isLoading: isSubmitting, spinnerAriaValueText: isSubmitting ? t('Adding members') : undefined }, t('Add')),
|
|
80
|
+
React.createElement(Button, { key: "cancel", variant: "link", onClick: onClose, isDisabled: isSubmitting }, t('Cancel')))));
|
|
81
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/Groups/AddMembersModal/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './AddMembersModal';
|
|
@@ -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;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;
|
|
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;IAC7C,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;CAC7B;AAKD,eAAO,MAAM,WAAW,GAAI,OAAO,MAAM,sBA2lBxC,CAAC"}
|
|
@@ -94,6 +94,7 @@ export const GroupSelect = (props) => {
|
|
|
94
94
|
// Group actions dropdown state
|
|
95
95
|
const hasGroupPermissions = ability.can(resourceActions.CREATE, resources.CASE_GROUPS);
|
|
96
96
|
const [showDropdown, setShowDropdown] = useState(hasGroupPermissions);
|
|
97
|
+
useEffect(() => setShowDropdown(hasGroupPermissions), [hasGroupPermissions]);
|
|
97
98
|
const [showInput, setShowInput] = useState(false);
|
|
98
99
|
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
|
|
99
100
|
const toggleIsDropdownOpen = () => setIsDropdownOpen(!isDropdownOpen);
|
|
@@ -310,11 +311,17 @@ export const GroupSelect = (props) => {
|
|
|
310
311
|
setAction('');
|
|
311
312
|
setInput(selectedGroup);
|
|
312
313
|
};
|
|
314
|
+
const handleAddMembers = () => {
|
|
315
|
+
var _a;
|
|
316
|
+
closeDropdown();
|
|
317
|
+
(_a = props.onAddMembers) === null || _a === void 0 ? void 0 : _a.call(props);
|
|
318
|
+
};
|
|
313
319
|
const dropdownItems = [
|
|
314
320
|
React.createElement(MenuItem, { className: "create-group-action", isDisabled: !ability.can(resourceActions.CREATE, resources.CASE_GROUPS), key: "create", onClick: onActionFocus(actions.create), "data-tracking-id": "manage-group-create" }, t('Create')),
|
|
315
321
|
React.createElement(Divider, { component: "li" }),
|
|
316
322
|
React.createElement(MenuItem, { className: "create-group-action", isDisabled: !selectedGroup || !ability.can(resourceActions.UPDATE, resources.CASE_GROUPS), key: "rename", onClick: onActionFocus(actions.rename), "data-tracking-id": "manage-group-rename" }, t('Rename')),
|
|
317
323
|
React.createElement(MenuItem, { className: "create-group-action", isDisabled: !selectedGroup || !ability.can(resourceActions.CREATE, resources.CASE_GROUPS), key: "duplicate", onClick: onActionFocus(actions.duplicate), "data-tracking-id": "manage-group-duplicate" }, t('Duplicate')),
|
|
324
|
+
React.createElement(MenuItem, { className: "create-group-action", isDisabled: !selectedGroup || !ability.can(resourceActions.CREATE, resources.CASE_GROUPS), key: "add-members", onClick: handleAddMembers, "data-tracking-id": "manage-group-add-members" }, t('Add members')),
|
|
318
325
|
React.createElement(MenuItem, { isDanger: true, className: "create-group-action del-btn", isDisabled: !selectedGroup || !ability.can(resourceActions.DELETE, resources.CASE_GROUPS), key: "delete", onClick: onActionFocus(actions.delete), "data-tracking-id": "manage-group-delete" }, t('Delete')),
|
|
319
326
|
];
|
|
320
327
|
const dropdownToggle = (toggleRef) => (React.createElement(MenuToggle, { isFullHeight: true, className: "pf-v6-u-ml-sm manage-group-actions-toggle-options pf-v6-u-p-md", ref: toggleRef, isDisabled: props.isDisabled || disableOnFetch, onClick: toggleIsDropdownOpen, isExpanded: isDropdownOpen, "data-tracking-id": "manage-group-toggle-options", "aria-label": "Group actions dropdown toggle", icon: React.createElement(CogIcon, null) }));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ManageGroupUsers.d.ts","sourceRoot":"","sources":["../../../../../src/components/Groups/ManageGroupUsers/ManageGroupUsers.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ManageGroupUsers.d.ts","sourceRoot":"","sources":["../../../../../src/components/Groups/ManageGroupUsers/ManageGroupUsers.tsx"],"names":[],"mappings":"AAMA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAanD,eAAO,MAAM,gBAAgB,yBAgN5B,CAAC"}
|
|
@@ -10,12 +10,14 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
import { SearchInput } from '@patternfly/react-core';
|
|
11
11
|
import { ErrorBoundary, usePrevious } from '@rh-support/components';
|
|
12
12
|
import { useGlobalStateContext } from '@rh-support/react-context';
|
|
13
|
+
import { ability, resourceActions, resources } from '@rh-support/user-permissions';
|
|
13
14
|
import isEmpty from 'lodash/isEmpty';
|
|
14
15
|
import React, { useEffect, useState } from 'react';
|
|
15
16
|
import { Trans, useTranslation } from 'react-i18next';
|
|
16
17
|
import { useLocation } from 'react-router-dom';
|
|
17
18
|
import { useCaseGroupMembers } 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
23
|
// TODO: Uncomment when updateUsers is migrated to GraphQL
|
|
@@ -26,7 +28,9 @@ export const ManageGroupUsers = () => {
|
|
|
26
28
|
const { globalMetadataState: { loggedInUsersAccount }, } = useGlobalStateContext();
|
|
27
29
|
const disableGroupSelect = !loggedInUsersAccount || !loggedInUsersAccount.data || !loggedInUsersAccount.data.accountNumber;
|
|
28
30
|
const [selectedGroup, setSelectedGroup] = useState();
|
|
29
|
-
const { data: groupUsers, loading: isFetching, fetchMembers } = useCaseGroupMembers();
|
|
31
|
+
const { data: groupUsers, loading: isFetching, fetchMembers, refetch } = useCaseGroupMembers();
|
|
32
|
+
const canManageCaseGroups = ability.can(resourceActions.CREATE, resources.CASE_GROUPS);
|
|
33
|
+
const [isAddMembersModalOpen, setIsAddMembersModalOpen] = useState(false);
|
|
30
34
|
// TODO: Uncomment when updateUsers is migrated to GraphQL
|
|
31
35
|
// function onPermissionError(error: Error, user: IGroupUser) {
|
|
32
36
|
// setData([...data]);
|
|
@@ -111,11 +115,15 @@ export const ManageGroupUsers = () => {
|
|
|
111
115
|
// />
|
|
112
116
|
// ),
|
|
113
117
|
// },
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
118
|
+
...(canManageCaseGroups
|
|
119
|
+
? [
|
|
120
|
+
{
|
|
121
|
+
id: 'default',
|
|
122
|
+
title: t('Default group'),
|
|
123
|
+
cell: (user, index) => (React.createElement(DefaultGroupSwitch, { id: `${index}`, onToggle: onDefaultToggle, group: selectedGroup, user: user })),
|
|
124
|
+
},
|
|
125
|
+
]
|
|
126
|
+
: []),
|
|
119
127
|
];
|
|
120
128
|
// filter out search query.
|
|
121
129
|
const [userSearch, setUserSearch] = useState('');
|
|
@@ -148,11 +156,12 @@ export const ManageGroupUsers = () => {
|
|
|
148
156
|
React.createElement("h2", { className: "pf-v6-u-pb-sm" }, t('Groups')),
|
|
149
157
|
React.createElement("p", null, t('To filter cases while searching, add or edit groups.'))),
|
|
150
158
|
React.createElement("div", { className: "toolbar pf-v6-u-justify-content-space-between" },
|
|
151
|
-
React.createElement(GroupSelect, { isDisabled: isFetching || disableGroupSelect, onSelect: onGroupSelect }),
|
|
159
|
+
React.createElement(GroupSelect, { isDisabled: isFetching || disableGroupSelect, onSelect: onGroupSelect, onAddMembers: () => setIsAddMembersModalOpen(true) }),
|
|
152
160
|
React.createElement("span", { className: "toolbar-right" },
|
|
153
161
|
React.createElement("label", { htmlFor: "account-group-filter" },
|
|
154
162
|
React.createElement(Trans, null, "Filter by")),
|
|
155
163
|
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('') }))),
|
|
156
164
|
React.createElement(ErrorBoundary, { errorMsgInfo: { message: t('There was an error loading group users list') } },
|
|
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 }))
|
|
165
|
+
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 })),
|
|
166
|
+
canManageCaseGroups && isAddMembersModalOpen && selectedGroup && (React.createElement(AddMembersModal, { group: selectedGroup, existingMembers: initialData, onSuccess: refetch, onClose: () => setIsAddMembersModalOpen(false) }))));
|
|
158
167
|
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ICaseLabel } from './types';
|
|
3
|
+
export type SaveCaseLabelResult = {
|
|
4
|
+
success: boolean;
|
|
5
|
+
fieldError?: string;
|
|
6
|
+
};
|
|
7
|
+
interface IProps {
|
|
8
|
+
isOpen: boolean;
|
|
9
|
+
addMode: boolean;
|
|
10
|
+
label?: ICaseLabel | null;
|
|
11
|
+
isSaving?: boolean;
|
|
12
|
+
onClose: () => void;
|
|
13
|
+
onSave: (name: string, options?: {
|
|
14
|
+
keepOpen?: boolean;
|
|
15
|
+
}) => Promise<SaveCaseLabelResult> | SaveCaseLabelResult;
|
|
16
|
+
}
|
|
17
|
+
export declare function AddEditCaseLabelModal({ isOpen, addMode, label, isSaving, onClose, onSave }: IProps): React.JSX.Element;
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=AddEditCaseLabelModal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AddEditCaseLabelModal.d.ts","sourceRoot":"","sources":["../../../../src/components/ManageCaseLabels/AddEditCaseLabelModal.tsx"],"names":[],"mappings":"AAeA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAGnD,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,MAAM,MAAM,mBAAmB,GAAG;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,UAAU,MAAM;IACZ,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IAC1B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC,mBAAmB,CAAC,GAAG,mBAAmB,CAAC;CAClH;AAED,wBAAgB,qBAAqB,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,QAAgB,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,MAAM,qBA4G1G"}
|
|
@@ -0,0 +1,72 @@
|
|
|
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 { Button, ButtonVariant, FormGroup, FormHelperText, HelperText, HelperTextItem, Modal, ModalBody, ModalFooter, ModalHeader, ModalVariant, TextInput, } from '@patternfly/react-core';
|
|
11
|
+
import isEmpty from 'lodash/isEmpty';
|
|
12
|
+
import React, { useEffect, useState } from 'react';
|
|
13
|
+
import { Trans, useTranslation } from 'react-i18next';
|
|
14
|
+
export function AddEditCaseLabelModal({ isOpen, addMode, label, isSaving = false, onClose, onSave }) {
|
|
15
|
+
const { t } = useTranslation();
|
|
16
|
+
const [name, setName] = useState('');
|
|
17
|
+
const [error, setError] = useState('');
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
if (isOpen) {
|
|
20
|
+
setName(addMode ? '' : (label === null || label === void 0 ? void 0 : label.name) || '');
|
|
21
|
+
setError('');
|
|
22
|
+
}
|
|
23
|
+
}, [isOpen, addMode, label]);
|
|
24
|
+
const validate = (value) => {
|
|
25
|
+
if (isEmpty(value.trim())) {
|
|
26
|
+
return t('Case label name cannot be empty.');
|
|
27
|
+
}
|
|
28
|
+
return '';
|
|
29
|
+
};
|
|
30
|
+
const handleSave = (...args_1) => __awaiter(this, [...args_1], void 0, function* (keepOpen = false) {
|
|
31
|
+
const validationError = validate(name);
|
|
32
|
+
if (!isEmpty(validationError)) {
|
|
33
|
+
setError(validationError);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const result = yield onSave(name.trim(), { keepOpen });
|
|
37
|
+
if (result.success) {
|
|
38
|
+
if (keepOpen) {
|
|
39
|
+
setName('');
|
|
40
|
+
setError('');
|
|
41
|
+
}
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
if (result.fieldError) {
|
|
45
|
+
setError(result.fieldError);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
const handleClose = () => {
|
|
49
|
+
setName('');
|
|
50
|
+
setError('');
|
|
51
|
+
onClose();
|
|
52
|
+
};
|
|
53
|
+
return (React.createElement(Modal, { id: "add-edit-case-label-modal", "aria-describedby": "add-edit-case-label-modal", isOpen: isOpen, onClose: handleClose, variant: ModalVariant.small },
|
|
54
|
+
React.createElement(ModalHeader, null,
|
|
55
|
+
React.createElement("h2", null, addMode ? t('Create new case label') : t('Rename case label'))),
|
|
56
|
+
React.createElement(ModalBody, null,
|
|
57
|
+
React.createElement(FormGroup, { label: t('Case label name'), isRequired: true },
|
|
58
|
+
React.createElement(TextInput, { isRequired: true, type: "text", id: "case-label-name-input", value: name, onChange: (_, value) => {
|
|
59
|
+
setName(value);
|
|
60
|
+
setError('');
|
|
61
|
+
}, placeholder: t('Enter a unique case label name'), validated: isEmpty(error) ? 'default' : 'error', isDisabled: isSaving }),
|
|
62
|
+
!isEmpty(error) && (React.createElement(FormHelperText, null,
|
|
63
|
+
React.createElement(HelperText, null,
|
|
64
|
+
React.createElement(HelperTextItem, { variant: "error" }, error)))))),
|
|
65
|
+
React.createElement(ModalFooter, null,
|
|
66
|
+
React.createElement(Button, { key: "save", variant: ButtonVariant.primary, onClick: () => handleSave(false), isDisabled: isEmpty(name.trim()) || !isEmpty(error) || isSaving, isLoading: isSaving },
|
|
67
|
+
React.createElement(Trans, null, "Save")),
|
|
68
|
+
addMode && (React.createElement(Button, { key: "save-and-new", variant: ButtonVariant.secondary, onClick: () => handleSave(true), isDisabled: isEmpty(name.trim()) || !isEmpty(error) || isSaving, isLoading: isSaving },
|
|
69
|
+
React.createElement(Trans, null, "Save & New"))),
|
|
70
|
+
React.createElement(Button, { key: "cancel", variant: ButtonVariant.link, onClick: handleClose, isDisabled: isSaving },
|
|
71
|
+
React.createElement(Trans, null, "Cancel")))));
|
|
72
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ManageCaseLabelsTab.d.ts","sourceRoot":"","sources":["../../../../src/components/ManageCaseLabels/ManageCaseLabelsTab.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAuC,MAAM,OAAO,CAAC;AAmC5D,wBAAgB,mBAAmB,sBAoQlC"}
|
|
@@ -0,0 +1,199 @@
|
|
|
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 { ActionList, ActionListItem, AlertVariant, Button, ButtonVariant, ModalVariant, SearchInput, } from '@patternfly/react-core';
|
|
11
|
+
import PencilAltIcon from '@patternfly/react-icons/dist/js/icons/pencil-alt-icon';
|
|
12
|
+
import TrashIcon from '@patternfly/react-icons/dist/js/icons/trash-icon';
|
|
13
|
+
import { ErrorBoundary, ToastNotification, useConfirmation } from '@rh-support/components';
|
|
14
|
+
import { useGlobalStateContext } from '@rh-support/react-context';
|
|
15
|
+
import isEmpty from 'lodash/isEmpty';
|
|
16
|
+
import React, { useEffect, useMemo, useState } from 'react';
|
|
17
|
+
import { Trans, useTranslation } from 'react-i18next';
|
|
18
|
+
import { useCaseLabels, useCreateCaseLabel, useDeleteCaseLabel, useUpdateCaseLabel, } from '../../hooks/useCaseLabelGraphQL';
|
|
19
|
+
import { ManageTable } from '../ManageTable';
|
|
20
|
+
import { AddEditCaseLabelModal } from './AddEditCaseLabelModal';
|
|
21
|
+
const isDuplicateCaseLabelGraphQLError = (error) => {
|
|
22
|
+
var _a, _b, _c, _d;
|
|
23
|
+
if (!error || typeof error !== 'object') {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
const apolloError = error;
|
|
27
|
+
const messages = [
|
|
28
|
+
...((_b = (_a = apolloError.graphQLErrors) === null || _a === void 0 ? void 0 : _a.map((graphQLError) => graphQLError.message || '')) !== null && _b !== void 0 ? _b : []),
|
|
29
|
+
...((_d = (_c = apolloError.errors) === null || _c === void 0 ? void 0 : _c.map((graphQLError) => graphQLError.message || '')) !== null && _d !== void 0 ? _d : []),
|
|
30
|
+
apolloError.message || '',
|
|
31
|
+
]
|
|
32
|
+
.join(' ')
|
|
33
|
+
.toLowerCase();
|
|
34
|
+
return messages.includes('duplicate value found');
|
|
35
|
+
};
|
|
36
|
+
export function ManageCaseLabelsTab() {
|
|
37
|
+
var _a;
|
|
38
|
+
const { t } = useTranslation();
|
|
39
|
+
const confirmation = useConfirmation();
|
|
40
|
+
const { globalMetadataState: { loggedInUsersAccount }, } = useGlobalStateContext();
|
|
41
|
+
const accountId = (_a = loggedInUsersAccount === null || loggedInUsersAccount === void 0 ? void 0 : loggedInUsersAccount.data) === null || _a === void 0 ? void 0 : _a.salesforceAccountId;
|
|
42
|
+
const { labels: fetchedLabels, loading: isFetchingLabels, error: labelsError, refetch } = useCaseLabels(accountId);
|
|
43
|
+
const { createCaseLabel, loading: isCreatingLabel } = useCreateCaseLabel();
|
|
44
|
+
const { updateCaseLabel, loading: isUpdatingLabel } = useUpdateCaseLabel();
|
|
45
|
+
const { deleteCaseLabel } = useDeleteCaseLabel();
|
|
46
|
+
const [labels, setLabels] = useState([]);
|
|
47
|
+
const [searchString, setSearchString] = useState('');
|
|
48
|
+
const [isModalOpen, setIsModalOpen] = useState(false);
|
|
49
|
+
const [isInAddMode, setIsInAddMode] = useState(true);
|
|
50
|
+
const [selectedLabel, setSelectedLabel] = useState(null);
|
|
51
|
+
useEffect(() => {
|
|
52
|
+
setLabels(fetchedLabels);
|
|
53
|
+
}, [fetchedLabels]);
|
|
54
|
+
const filteredLabels = useMemo(() => {
|
|
55
|
+
if (isEmpty(searchString)) {
|
|
56
|
+
return labels;
|
|
57
|
+
}
|
|
58
|
+
return labels.filter((label) => label.name.toLowerCase().includes(searchString.toLowerCase()));
|
|
59
|
+
}, [labels, searchString]);
|
|
60
|
+
const onOpenAddModal = () => {
|
|
61
|
+
setIsInAddMode(true);
|
|
62
|
+
setSelectedLabel(null);
|
|
63
|
+
setIsModalOpen(true);
|
|
64
|
+
};
|
|
65
|
+
const onOpenEditModal = (label) => {
|
|
66
|
+
setIsInAddMode(false);
|
|
67
|
+
setSelectedLabel(label);
|
|
68
|
+
setIsModalOpen(true);
|
|
69
|
+
};
|
|
70
|
+
const closeModal = () => {
|
|
71
|
+
setIsModalOpen(false);
|
|
72
|
+
setSelectedLabel(null);
|
|
73
|
+
setIsInAddMode(true);
|
|
74
|
+
};
|
|
75
|
+
const onSaveLabel = (name, options) => __awaiter(this, void 0, void 0, function* () {
|
|
76
|
+
if (isInAddMode) {
|
|
77
|
+
if (!accountId) {
|
|
78
|
+
ToastNotification.addDangerMessage(t('Unable to create case label. Account information is missing.'));
|
|
79
|
+
return { success: false };
|
|
80
|
+
}
|
|
81
|
+
try {
|
|
82
|
+
yield createCaseLabel(name, accountId);
|
|
83
|
+
yield refetch();
|
|
84
|
+
ToastNotification.addSuccessMessage(t('Case label has been successfully created.'));
|
|
85
|
+
if (!(options === null || options === void 0 ? void 0 : options.keepOpen)) {
|
|
86
|
+
closeModal();
|
|
87
|
+
}
|
|
88
|
+
return { success: true };
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
if (isDuplicateCaseLabelGraphQLError(error)) {
|
|
92
|
+
return {
|
|
93
|
+
success: false,
|
|
94
|
+
fieldError: t('Label name already in use. Try a different name.'),
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
ToastNotification.addDangerMessage(t('Case label failed to create.'));
|
|
98
|
+
return { success: false };
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (selectedLabel) {
|
|
102
|
+
try {
|
|
103
|
+
yield updateCaseLabel(selectedLabel.id, name);
|
|
104
|
+
yield refetch();
|
|
105
|
+
ToastNotification.addSuccessMessage(t('Case label has been successfully updated.'));
|
|
106
|
+
closeModal();
|
|
107
|
+
return { success: true };
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
if (isDuplicateCaseLabelGraphQLError(error)) {
|
|
111
|
+
return {
|
|
112
|
+
success: false,
|
|
113
|
+
fieldError: t('Label name already in use. Try a different name.'),
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
ToastNotification.addDangerMessage(t('Case label failed to update.'));
|
|
117
|
+
return { success: false };
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return { success: false };
|
|
121
|
+
});
|
|
122
|
+
const onDeleteLabel = (label) => __awaiter(this, void 0, void 0, function* () {
|
|
123
|
+
try {
|
|
124
|
+
yield confirmation({
|
|
125
|
+
catchOnCancel: true,
|
|
126
|
+
confirmText: t('Delete label'),
|
|
127
|
+
confirmButtonVariant: ButtonVariant.danger,
|
|
128
|
+
cancelText: t('Cancel'),
|
|
129
|
+
modalVariant: ModalVariant.large,
|
|
130
|
+
title: t('Delete case label'),
|
|
131
|
+
description: (React.createElement("div", { className: "case-label-delete-description", style: { display: 'flex', flexDirection: 'column', gap: '1.5rem' } },
|
|
132
|
+
React.createElement("div", null, t('Are you sure you want to delete "{{name}}" case label?', { name: label.name })),
|
|
133
|
+
React.createElement("div", { style: { whiteSpace: 'nowrap' } },
|
|
134
|
+
t('This label is currently assigned to'),
|
|
135
|
+
' ',
|
|
136
|
+
React.createElement("strong", null, t('{{count}} cases', { count: label.assignedCaseCount })),
|
|
137
|
+
'. ',
|
|
138
|
+
t('Deleting it will remove the label from all associated cases.')))),
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
catch (_a) {
|
|
142
|
+
// user cancelled
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
try {
|
|
146
|
+
yield deleteCaseLabel(label.id);
|
|
147
|
+
yield refetch();
|
|
148
|
+
ToastNotification.addSuccessMessage(t('Case label has been successfully removed.'));
|
|
149
|
+
}
|
|
150
|
+
catch (_b) {
|
|
151
|
+
ToastNotification.addDangerMessage(t('Case label failed to remove.'));
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
const onViewAssignedCases = (label) => {
|
|
155
|
+
// Placeholder until case-list filter by label is wired
|
|
156
|
+
ToastNotification.addInfoMessage(t(`View cases assigned to "${label.name}" (coming soon)`));
|
|
157
|
+
};
|
|
158
|
+
const columns = [
|
|
159
|
+
{
|
|
160
|
+
accessor: (label) => label.name,
|
|
161
|
+
sortable: false,
|
|
162
|
+
id: 'case-label-row',
|
|
163
|
+
title: '',
|
|
164
|
+
cellWidth: 100,
|
|
165
|
+
cell: (label) => (React.createElement("div", { className: "case-label-row" },
|
|
166
|
+
React.createElement("div", { className: "case-label-row__info" },
|
|
167
|
+
React.createElement("div", { className: "pf-v6-u-font-weight-bold" }, label.name),
|
|
168
|
+
React.createElement("div", { className: "pf-v6-u-color-200 pf-v6-u-font-size-sm" }, t('{{count}} cases assigned', { count: label.assignedCaseCount }))),
|
|
169
|
+
React.createElement("div", { className: "case-label-row__actions" },
|
|
170
|
+
label.assignedCaseCount > 0 && (React.createElement(Button, { variant: ButtonVariant.link, isInline: true, onClick: () => onViewAssignedCases(label), "data-tracking-id": "case-label-view-assigned-cases" },
|
|
171
|
+
React.createElement(Trans, null, "View assigned cases"))),
|
|
172
|
+
React.createElement(ActionList, { isIconList: true },
|
|
173
|
+
React.createElement(ActionListItem, null,
|
|
174
|
+
React.createElement(Button, { icon: React.createElement(PencilAltIcon, null), "aria-label": t('Edit case label {{name}}', { name: label.name }), variant: "plain", onClick: () => onOpenEditModal(label), "data-tracking-id": "case-label-edit" })),
|
|
175
|
+
React.createElement(ActionListItem, null,
|
|
176
|
+
React.createElement(Button, { icon: React.createElement(TrashIcon, null), "aria-label": t('Delete case label {{name}}', { name: label.name }), variant: "plain", onClick: () => onDeleteLabel(label), "data-tracking-id": "case-label-delete" })))))),
|
|
177
|
+
},
|
|
178
|
+
];
|
|
179
|
+
return (React.createElement(React.Fragment, null,
|
|
180
|
+
React.createElement("header", null,
|
|
181
|
+
React.createElement("h2", null, t('Case labels')),
|
|
182
|
+
React.createElement("p", null,
|
|
183
|
+
React.createElement(Trans, null, "Case labels help you organize and categorize cases with custom tags, making them easier to find, filter, and manage."))),
|
|
184
|
+
React.createElement("div", { className: "toolbar case-labels-toolbar" },
|
|
185
|
+
React.createElement("div", { className: "toolbar-left" },
|
|
186
|
+
React.createElement("label", { htmlFor: "search-case-label-input" },
|
|
187
|
+
React.createElement(Trans, null, "Case labels")),
|
|
188
|
+
React.createElement(SearchInput, { className: "pf-v6-u-flex-grow-1 pf-v6-c-search-input pf-v6-u-background-color-100", value: searchString, id: "search-case-label-input", placeholder: t('Search case label by name.'), "aria-label": t('Search case label by name'), onChange: (_, val) => setSearchString(val), onClear: () => setSearchString('') }),
|
|
189
|
+
React.createElement("span", { className: "pf-v6-u-ml-sm" },
|
|
190
|
+
React.createElement(Button, { variant: ButtonVariant.primary, isInline: true, onClick: onOpenAddModal, "data-tracking-id": "case-label-add-button" },
|
|
191
|
+
React.createElement(Trans, null, "Add")))),
|
|
192
|
+
React.createElement("div", { className: "toolbar-right case-labels-toolbar__loaded pf-v6-u-color-200" }, t('{{loaded}} of {{total}} loaded.', {
|
|
193
|
+
loaded: filteredLabels.length,
|
|
194
|
+
total: filteredLabels.length,
|
|
195
|
+
}))),
|
|
196
|
+
React.createElement(AddEditCaseLabelModal, { isOpen: isModalOpen, addMode: isInAddMode, label: selectedLabel, isSaving: isCreatingLabel || isUpdatingLabel, onClose: closeModal, onSave: onSaveLabel }),
|
|
197
|
+
React.createElement(ErrorBoundary, { errorMsgInfo: { message: t('There was an error loading case labels list') } },
|
|
198
|
+
React.createElement(ManageTable, { ariaLabel: t('Table to manage case labels'), columns: columns, data: filteredLabels, errorVariant: AlertVariant.warning, isFetching: isFetchingLabels, isError: !!labelsError, errorTitle: t('Case labels error'), errorComponent: React.createElement(Trans, null, "Could not get case labels"), pagination: false, noResultText: t('There are no results to display. Try adding a case label or refining your search') }))));
|
|
199
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/ManageCaseLabels/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC"}
|