@rh-support/manage 2.5.272 → 2.5.276
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 +46 -18
- 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 +80 -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/DefualtGroupSwitch/DefaultGroupSwitch.d.ts +5 -3
- package/lib/esm/components/Groups/DefualtGroupSwitch/DefaultGroupSwitch.d.ts.map +1 -1
- package/lib/esm/components/Groups/DefualtGroupSwitch/DefaultGroupSwitch.js +21 -14
- 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 +160 -85
- package/lib/esm/components/Groups/ManageGroupUsers/ManageGroupUsers.d.ts.map +1 -1
- package/lib/esm/components/Groups/ManageGroupUsers/ManageGroupUsers.js +163 -42
- 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 +97 -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 +220 -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/PreferencesACL.d.ts.map +1 -1
- package/lib/esm/components/ManagePreferences/sections/PreferencesACL.js +3 -4
- package/lib/esm/components/ManagePreferences/sections/PreferencesCaseCreate.d.ts.map +1 -1
- package/lib/esm/components/ManagePreferences/sections/PreferencesCaseCreate.js +73 -58
- package/lib/esm/components/ManagePreferences/sections/PreferencesCaseView.d.ts.map +1 -1
- package/lib/esm/components/ManagePreferences/sections/PreferencesCaseView.js +43 -98
- 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 +42 -0
- package/lib/esm/hooks/useCaseGroupGraphQL.d.ts.map +1 -0
- package/lib/esm/hooks/useCaseGroupGraphQL.js +109 -0
- 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 +104 -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/hooks/useVersionsDiffer.d.ts.map +1 -1
- package/lib/esm/index.js +1 -0
- package/lib/esm/scss/_main.scss +77 -0
- package/lib/esm/utils/caseGroupMapper.d.ts +18 -0
- package/lib/esm/utils/caseGroupMapper.d.ts.map +1 -0
- package/lib/esm/utils/caseGroupMapper.js +50 -0
- package/package.json +11 -8
|
@@ -7,39 +7,87 @@ 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 {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
10
|
+
import { Button, Modal, ModalBody, ModalFooter, ModalHeader, ModalVariant, SearchInput, Tooltip, } from '@patternfly/react-core';
|
|
11
|
+
import { ErrorBoundary, ToastNotification, usePrevious } from '@rh-support/components';
|
|
12
|
+
import { GlobalMetadataReducerConstants, useGlobalDispatchContext, useGlobalStateContext, } from '@rh-support/react-context';
|
|
13
|
+
import { ability, resourceActions, resources } from '@rh-support/user-permissions';
|
|
14
14
|
import isEmpty from 'lodash/isEmpty';
|
|
15
15
|
import React, { useEffect, useMemo, useState } from 'react';
|
|
16
16
|
import { Trans, useTranslation } from 'react-i18next';
|
|
17
17
|
import { useLocation } from 'react-router-dom';
|
|
18
|
+
import { useCaseGroupMembers, useDeleteCaseGroupMember } 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
|
|
24
|
+
// import { GroupUserPermissionsSelect } from '../GroupUserPermissionsSelect';
|
|
25
|
+
const RemoveMemberButton = ({ user, onRemove, isDisabled }) => {
|
|
26
|
+
const { t } = useTranslation();
|
|
27
|
+
const button = (React.createElement(Button, { variant: "link", isDanger: true, onClick: () => onRemove(user), isAriaDisabled: user.isOrgAdmin || isDisabled }, t('Remove')));
|
|
28
|
+
if (user.isOrgAdmin) {
|
|
29
|
+
return (React.createElement(Tooltip, { content: t('Organization Administrators cannot be removed because they have access to all groups') }, button));
|
|
30
|
+
}
|
|
31
|
+
return button;
|
|
32
|
+
};
|
|
22
33
|
export const ManageGroupUsers = () => {
|
|
34
|
+
var _a, _b;
|
|
23
35
|
const { t } = useTranslation();
|
|
24
36
|
const location = useLocation();
|
|
25
|
-
const { globalMetadataState: { loggedInUsersAccount }, } = useGlobalStateContext();
|
|
37
|
+
const { globalMetadataState: { caseGroups, loggedInUsersAccount, loggedInUser }, } = useGlobalStateContext();
|
|
38
|
+
const dispatchToGlobalMetadataReducer = useGlobalDispatchContext();
|
|
26
39
|
const disableGroupSelect = !loggedInUsersAccount || !loggedInUsersAccount.data || !loggedInUsersAccount.data.accountNumber;
|
|
27
40
|
const [selectedGroup, setSelectedGroup] = useState();
|
|
28
|
-
const {
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
41
|
+
const { data: groupUsers, loading: isFetching, fetchMembers, refetch } = useCaseGroupMembers();
|
|
42
|
+
const defaultCaseGroupId = (_b = (_a = loggedInUser === null || loggedInUser === void 0 ? void 0 : loggedInUser.data) === null || _a === void 0 ? void 0 : _a.defaultCaseGroup) !== null && _b !== void 0 ? _b : null;
|
|
43
|
+
const membersWithOrgAdmin = useMemo(() => {
|
|
44
|
+
var _a, _b, _c, _d;
|
|
45
|
+
const loggedInContact = loggedInUser === null || loggedInUser === void 0 ? void 0 : loggedInUser.data;
|
|
46
|
+
const selectedGroupId = selectedGroup === null || selectedGroup === void 0 ? void 0 : selectedGroup.groupNum;
|
|
47
|
+
const syncLoggedInUserDefault = (members) => {
|
|
48
|
+
if (!(loggedInContact === null || loggedInContact === void 0 ? void 0 : loggedInContact.ssoUsername) || !selectedGroupId)
|
|
49
|
+
return members;
|
|
50
|
+
return members.map((member) => member.ssoUsername === loggedInContact.ssoUsername
|
|
51
|
+
? Object.assign(Object.assign({}, member), { isDefault: defaultCaseGroupId === selectedGroupId }) : member);
|
|
52
|
+
};
|
|
53
|
+
const members = syncLoggedInUserDefault(groupUsers || []);
|
|
54
|
+
const user = loggedInContact;
|
|
55
|
+
if (!(user === null || user === void 0 ? void 0 : user.isOrgAdmin) || !user.ssoUsername || !selectedGroup)
|
|
56
|
+
return members;
|
|
57
|
+
const alreadyPresent = members.some((m) => m.ssoUsername === user.ssoUsername);
|
|
58
|
+
if (alreadyPresent)
|
|
59
|
+
return members;
|
|
60
|
+
const syntheticEntry = {
|
|
61
|
+
firstName: (_a = user.firstName) !== null && _a !== void 0 ? _a : '',
|
|
62
|
+
lastName: (_b = user.lastName) !== null && _b !== void 0 ? _b : '',
|
|
63
|
+
isOrgAdmin: true,
|
|
64
|
+
access: true,
|
|
65
|
+
write: false,
|
|
66
|
+
isDefault: defaultCaseGroupId === selectedGroup.groupNum,
|
|
67
|
+
ssoUsername: user.ssoUsername,
|
|
68
|
+
email: (_c = user.email) !== null && _c !== void 0 ? _c : '',
|
|
69
|
+
contactSfId: (_d = user.id) !== null && _d !== void 0 ? _d : '',
|
|
70
|
+
memberRecordId: '',
|
|
71
|
+
};
|
|
72
|
+
return [...members, syntheticEntry];
|
|
73
|
+
}, [groupUsers, loggedInUser === null || loggedInUser === void 0 ? void 0 : loggedInUser.data, selectedGroup, defaultCaseGroupId]);
|
|
74
|
+
const canManageCaseGroups = ability.can(resourceActions.CREATE, resources.CASE_GROUPS);
|
|
75
|
+
const [isAddMembersModalOpen, setIsAddMembersModalOpen] = useState(false);
|
|
76
|
+
const [memberToRemove, setMemberToRemove] = useState(null);
|
|
77
|
+
const { deleteMember, loading: isDeleting } = useDeleteCaseGroupMember();
|
|
78
|
+
// TODO: Uncomment when updateUsers is migrated to GraphQL
|
|
79
|
+
// function onPermissionError(error: Error, user: IGroupUser) {
|
|
80
|
+
// setData([...data]);
|
|
81
|
+
// const message = t(`Could not change permission for {{user}}: {{error}}`, {
|
|
82
|
+
// user: `${user.firstName} ${user.lastName}`,
|
|
83
|
+
// error: error.message,
|
|
84
|
+
// });
|
|
85
|
+
// ToastNotification.addDangerMessage(message);
|
|
86
|
+
// }
|
|
39
87
|
// set and sort fetched data.
|
|
40
|
-
const [initialData, setInitialData] = useState(
|
|
41
|
-
const [data, setData] = useState(
|
|
42
|
-
useEffect(() => setAllData(
|
|
88
|
+
const [initialData, setInitialData] = useState(membersWithOrgAdmin);
|
|
89
|
+
const [data, setData] = useState(membersWithOrgAdmin);
|
|
90
|
+
useEffect(() => setAllData(membersWithOrgAdmin || []), [membersWithOrgAdmin]);
|
|
43
91
|
function setAllData(users) {
|
|
44
92
|
setInitialData(users);
|
|
45
93
|
setData(users);
|
|
@@ -58,21 +106,63 @@ export const ManageGroupUsers = () => {
|
|
|
58
106
|
return tempUser;
|
|
59
107
|
}));
|
|
60
108
|
};
|
|
109
|
+
const onDefaultToggleSuccess = (user, isChecked) => {
|
|
110
|
+
var _a;
|
|
111
|
+
if (user.ssoUsername !== ((_a = loggedInUser === null || loggedInUser === void 0 ? void 0 : loggedInUser.data) === null || _a === void 0 ? void 0 : _a.ssoUsername) || !selectedGroup)
|
|
112
|
+
return;
|
|
113
|
+
const groupId = isChecked ? selectedGroup.groupNum : null;
|
|
114
|
+
const updatedLoggedInUserData = Object.assign(Object.assign({}, loggedInUser.data), { defaultCaseGroup: groupId });
|
|
115
|
+
dispatchToGlobalMetadataReducer({
|
|
116
|
+
type: GlobalMetadataReducerConstants.setLoggedInUser,
|
|
117
|
+
payload: {
|
|
118
|
+
loggedInUser: Object.assign(Object.assign({}, loggedInUser), { data: updatedLoggedInUserData }),
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
if (caseGroups === null || caseGroups === void 0 ? void 0 : caseGroups.data) {
|
|
122
|
+
const updatedGroups = caseGroups.data.map((group) => (Object.assign(Object.assign({}, group), { isDefault: groupId !== null && group.groupNum === groupId })));
|
|
123
|
+
dispatchToGlobalMetadataReducer({
|
|
124
|
+
type: GlobalMetadataReducerConstants.setCaseGroups,
|
|
125
|
+
payload: {
|
|
126
|
+
caseGroups: Object.assign(Object.assign({}, caseGroups), { data: updatedGroups }),
|
|
127
|
+
},
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
};
|
|
61
131
|
const onGroupSelect = (group) => __awaiter(void 0, void 0, void 0, function* () {
|
|
62
132
|
setSelectedGroup(group);
|
|
63
133
|
if (group) {
|
|
64
|
-
|
|
134
|
+
fetchMembers(group.groupNum);
|
|
65
135
|
}
|
|
66
136
|
else {
|
|
67
|
-
|
|
137
|
+
setAllData([]);
|
|
68
138
|
}
|
|
69
139
|
});
|
|
70
|
-
function
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
140
|
+
const handleRemoveMember = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
141
|
+
if (!(memberToRemove === null || memberToRemove === void 0 ? void 0 : memberToRemove.memberRecordId))
|
|
142
|
+
return;
|
|
143
|
+
try {
|
|
144
|
+
yield deleteMember(memberToRemove.memberRecordId);
|
|
145
|
+
ToastNotification.addSuccessMessage(t('{{name}} has been removed from the group', {
|
|
146
|
+
name: `${memberToRemove.firstName} ${memberToRemove.lastName}`,
|
|
147
|
+
}));
|
|
148
|
+
refetch();
|
|
149
|
+
}
|
|
150
|
+
catch (error) {
|
|
151
|
+
ToastNotification.addDangerMessage(t('Could not remove member from group: {{message}}', {
|
|
152
|
+
message: error instanceof Error ? error.message : String(error),
|
|
153
|
+
}));
|
|
154
|
+
}
|
|
155
|
+
finally {
|
|
156
|
+
setMemberToRemove(null);
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
// TODO: Uncomment when updateUsers is migrated to GraphQL
|
|
160
|
+
// function onPermissionsChange(user: IGroupUser) {
|
|
161
|
+
// const initialUsers = initialData.map((value) => (value.ssoUsername === user.ssoUsername ? user : value));
|
|
162
|
+
// const users = data.map((value) => (value.ssoUsername === user.ssoUsername ? user : value));
|
|
163
|
+
// setInitialData(initialUsers);
|
|
164
|
+
// setData(users);
|
|
165
|
+
// }
|
|
76
166
|
const columns = [
|
|
77
167
|
{
|
|
78
168
|
accessor: (user) => user.firstName,
|
|
@@ -92,16 +182,38 @@ export const ManageGroupUsers = () => {
|
|
|
92
182
|
id: 'sso-username',
|
|
93
183
|
title: t('Login'),
|
|
94
184
|
},
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}
|
|
185
|
+
// TODO: Uncomment when updateUsers is migrated to GraphQL
|
|
186
|
+
// {
|
|
187
|
+
// id: 'permissions',
|
|
188
|
+
// title: t('Permissions'),
|
|
189
|
+
// cell: (user) =>
|
|
190
|
+
// user.isOrgAdmin ? (
|
|
191
|
+
// t('Admin/Full access')
|
|
192
|
+
// ) : (
|
|
193
|
+
// <GroupUserPermissionsSelect
|
|
194
|
+
// onChange={onPermissionsChange}
|
|
195
|
+
// account={loggedInUsersAccount.data}
|
|
196
|
+
// group={selectedGroup}
|
|
197
|
+
// users={data}
|
|
198
|
+
// user={user}
|
|
199
|
+
// onError={onPermissionError}
|
|
200
|
+
// />
|
|
201
|
+
// ),
|
|
202
|
+
// },
|
|
203
|
+
...(canManageCaseGroups
|
|
204
|
+
? [
|
|
205
|
+
{
|
|
206
|
+
id: 'default',
|
|
207
|
+
title: t('Default group'),
|
|
208
|
+
cell: (user, index) => (React.createElement(DefaultGroupSwitch, { id: `${index}`, onToggle: onDefaultToggle, onToggleSuccess: onDefaultToggleSuccess, group: selectedGroup, user: user })),
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
id: 'remove',
|
|
212
|
+
title: '',
|
|
213
|
+
cell: (user) => (React.createElement(RemoveMemberButton, { user: user, onRemove: setMemberToRemove, isDisabled: isDeleting })),
|
|
214
|
+
},
|
|
215
|
+
]
|
|
216
|
+
: []),
|
|
105
217
|
];
|
|
106
218
|
// filter out search query.
|
|
107
219
|
const [userSearch, setUserSearch] = useState('');
|
|
@@ -121,12 +233,12 @@ export const ManageGroupUsers = () => {
|
|
|
121
233
|
else {
|
|
122
234
|
setData(initialData);
|
|
123
235
|
}
|
|
124
|
-
}, [initialData, userSearch, setData, previousUserSearch,
|
|
236
|
+
}, [initialData, userSearch, setData, previousUserSearch, membersWithOrgAdmin]);
|
|
125
237
|
useEffect(() => {
|
|
126
238
|
if (location.pathname !== '/manage/groups') {
|
|
127
239
|
return;
|
|
128
240
|
}
|
|
129
|
-
setAllData(
|
|
241
|
+
setAllData(membersWithOrgAdmin || []);
|
|
130
242
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
131
243
|
}, [location.pathname, loggedInUsersAccount.data]);
|
|
132
244
|
return (React.createElement(React.Fragment, null,
|
|
@@ -134,11 +246,20 @@ export const ManageGroupUsers = () => {
|
|
|
134
246
|
React.createElement("h2", { className: "pf-v6-u-pb-sm" }, t('Groups')),
|
|
135
247
|
React.createElement("p", null, t('To filter cases while searching, add or edit groups.'))),
|
|
136
248
|
React.createElement("div", { className: "toolbar pf-v6-u-justify-content-space-between" },
|
|
137
|
-
React.createElement(GroupSelect, { isDisabled: isFetching || disableGroupSelect, onSelect: onGroupSelect }),
|
|
249
|
+
React.createElement(GroupSelect, { isDisabled: isFetching || disableGroupSelect, onSelect: onGroupSelect, onAddMembers: () => setIsAddMembersModalOpen(true) }),
|
|
138
250
|
React.createElement("span", { className: "toolbar-right" },
|
|
139
251
|
React.createElement("label", { htmlFor: "account-group-filter" },
|
|
140
252
|
React.createElement(Trans, null, "Filter by")),
|
|
141
253
|
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
254
|
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 }))
|
|
255
|
+
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 })),
|
|
256
|
+
memberToRemove && (React.createElement(Modal, { variant: ModalVariant.small, isOpen: true, onClose: () => setMemberToRemove(null), "aria-label": t('Confirm removal') },
|
|
257
|
+
React.createElement(ModalHeader, { title: t('Remove member') }),
|
|
258
|
+
React.createElement(ModalBody, null, t('Are you sure you want to remove {{name}} from this group?', {
|
|
259
|
+
name: `${memberToRemove.firstName} ${memberToRemove.lastName}`,
|
|
260
|
+
})),
|
|
261
|
+
React.createElement(ModalFooter, null,
|
|
262
|
+
React.createElement(Button, { variant: "danger", onClick: handleRemoveMember, isLoading: isDeleting, isDisabled: isDeleting }, t('Remove')),
|
|
263
|
+
React.createElement(Button, { variant: "link", onClick: () => setMemberToRemove(null), isDisabled: isDeleting }, t('Cancel'))))),
|
|
264
|
+
canManageCaseGroups && isAddMembersModalOpen && selectedGroup && (React.createElement(AddMembersModal, { group: selectedGroup, existingMembers: initialData, onSuccess: refetch, onClose: () => setIsAddMembersModalOpen(false) }))));
|
|
144
265
|
};
|
|
@@ -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":"AAkBA,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,qBAkJ1G"}
|
|
@@ -0,0 +1,97 @@
|
|
|
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, Flex, FlexItem, FormGroup, FormHelperText, HelperText, HelperTextItem, Modal, ModalBody, ModalFooter, ModalHeader, ModalVariant, TextInput, } from '@patternfly/react-core';
|
|
11
|
+
import { CASE_LABEL_NAME_MAX_LENGTH } from '@rh-support/utils';
|
|
12
|
+
import isEmpty from 'lodash/isEmpty';
|
|
13
|
+
import React, { useEffect, useState } from 'react';
|
|
14
|
+
import { Trans, useTranslation } from 'react-i18next';
|
|
15
|
+
export function AddEditCaseLabelModal({ isOpen, addMode, label, isSaving = false, onClose, onSave }) {
|
|
16
|
+
const { t } = useTranslation();
|
|
17
|
+
const [name, setName] = useState('');
|
|
18
|
+
const [error, setError] = useState('');
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
if (isOpen) {
|
|
21
|
+
setName(addMode ? '' : (label === null || label === void 0 ? void 0 : label.name) || '');
|
|
22
|
+
setError('');
|
|
23
|
+
}
|
|
24
|
+
}, [isOpen, addMode, label]);
|
|
25
|
+
const isOverMaxLength = name.length > CASE_LABEL_NAME_MAX_LENGTH;
|
|
26
|
+
const isNameEmpty = isEmpty(name.trim());
|
|
27
|
+
const canSave = !isNameEmpty && !isOverMaxLength && !isSaving;
|
|
28
|
+
const resetForm = () => {
|
|
29
|
+
setName('');
|
|
30
|
+
setError('');
|
|
31
|
+
};
|
|
32
|
+
const handleSave = () => __awaiter(this, void 0, void 0, function* () {
|
|
33
|
+
if (isNameEmpty) {
|
|
34
|
+
setError(t('Case label name cannot be empty.'));
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
if (isOverMaxLength) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const result = yield onSave(name.trim(), { keepOpen: false });
|
|
41
|
+
if (!result.success && result.fieldError) {
|
|
42
|
+
setError(result.fieldError);
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
const handleSaveAndNew = () => __awaiter(this, void 0, void 0, function* () {
|
|
46
|
+
if (isNameEmpty) {
|
|
47
|
+
setError(t('Case label name cannot be empty.'));
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (isOverMaxLength) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const result = yield onSave(name.trim(), { keepOpen: true });
|
|
54
|
+
if (result.success) {
|
|
55
|
+
resetForm();
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (result.fieldError) {
|
|
59
|
+
setError(result.fieldError);
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
const handleClose = () => {
|
|
63
|
+
resetForm();
|
|
64
|
+
onClose();
|
|
65
|
+
};
|
|
66
|
+
return (React.createElement(Modal, { id: "add-edit-case-label-modal", "aria-describedby": "add-edit-case-label-modal", isOpen: isOpen, onClose: handleClose, variant: ModalVariant.small },
|
|
67
|
+
React.createElement(ModalHeader, null,
|
|
68
|
+
React.createElement("h2", null, addMode ? t('Create new case label') : t('Rename case label'))),
|
|
69
|
+
React.createElement(ModalBody, null,
|
|
70
|
+
React.createElement(FormGroup, { label: t('Case label name'), isRequired: true },
|
|
71
|
+
React.createElement(TextInput, { isRequired: true, type: "text", id: "case-label-name-input", value: name, onChange: (_, value) => {
|
|
72
|
+
setName(value);
|
|
73
|
+
if (!isEmpty(error)) {
|
|
74
|
+
setError('');
|
|
75
|
+
}
|
|
76
|
+
}, placeholder: t('Enter a unique case label name'), validated: isOverMaxLength || !isEmpty(error) ? 'error' : 'default', isDisabled: isSaving }),
|
|
77
|
+
React.createElement(FormHelperText, null,
|
|
78
|
+
React.createElement(Flex, { justifyContent: { default: 'justifyContentFlexEnd' } },
|
|
79
|
+
React.createElement(FlexItem, null,
|
|
80
|
+
React.createElement(HelperText, null,
|
|
81
|
+
React.createElement(HelperTextItem, { variant: "default", className: `pf-v6-u-font-size-sm ${isOverMaxLength
|
|
82
|
+
? 'pf-v6-u-text-color-status-danger'
|
|
83
|
+
: 'pf-v6-u-text-color-subtle'}` }, t('{{count}}/{{max}} characters', {
|
|
84
|
+
count: name.length,
|
|
85
|
+
max: CASE_LABEL_NAME_MAX_LENGTH,
|
|
86
|
+
})))))),
|
|
87
|
+
!isEmpty(error) && (React.createElement(FormHelperText, null,
|
|
88
|
+
React.createElement(HelperText, null,
|
|
89
|
+
React.createElement(HelperTextItem, { variant: "error" }, error)))))),
|
|
90
|
+
React.createElement(ModalFooter, null,
|
|
91
|
+
React.createElement(Button, { key: "save", variant: ButtonVariant.primary, onClick: handleSave, isDisabled: !canSave, isLoading: isSaving },
|
|
92
|
+
React.createElement(Trans, null, "Save")),
|
|
93
|
+
addMode && (React.createElement(Button, { key: "save-and-new", variant: ButtonVariant.secondary, onClick: handleSaveAndNew, isDisabled: !canSave, isLoading: isSaving },
|
|
94
|
+
React.createElement(Trans, null, "Save & New"))),
|
|
95
|
+
React.createElement(Button, { key: "cancel", variant: ButtonVariant.link, onClick: handleClose, isDisabled: isSaving },
|
|
96
|
+
React.createElement(Trans, null, "Cancel")))));
|
|
97
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ManageCaseLabelsTab.d.ts","sourceRoot":"","sources":["../../../../src/components/ManageCaseLabels/ManageCaseLabelsTab.tsx"],"names":[],"mappings":"AAoBA,OAAO,KAAuC,MAAM,OAAO,CAAC;AAoC5D,wBAAgB,mBAAmB,sBAwUlC"}
|
|
@@ -0,0 +1,220 @@
|
|
|
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, EmptyState, EmptyStateBody, EmptyStateFooter, EmptyStateVariant, ModalVariant, SearchInput, } from '@patternfly/react-core';
|
|
11
|
+
import CubesIcon from '@patternfly/react-icons/dist/js/icons/cubes-icon';
|
|
12
|
+
import PencilAltIcon from '@patternfly/react-icons/dist/js/icons/pencil-alt-icon';
|
|
13
|
+
import TrashIcon from '@patternfly/react-icons/dist/js/icons/trash-icon';
|
|
14
|
+
import { ErrorBoundary, ToastNotification, useConfirmation } from '@rh-support/components';
|
|
15
|
+
import { useGlobalStateContext } from '@rh-support/react-context';
|
|
16
|
+
import { getStringifiedParams } from '@rh-support/utils';
|
|
17
|
+
import isEmpty from 'lodash/isEmpty';
|
|
18
|
+
import React, { useEffect, useMemo, useState } from 'react';
|
|
19
|
+
import { Trans, useTranslation } from 'react-i18next';
|
|
20
|
+
import { useHistory } from 'react-router-dom';
|
|
21
|
+
import { useCaseLabels, useCreateCaseLabel, useDeleteCaseLabel, useUpdateCaseLabel, } from '../../hooks/useCaseLabelGraphQL';
|
|
22
|
+
import { ManageTable } from '../ManageTable';
|
|
23
|
+
import { AddEditCaseLabelModal } from './AddEditCaseLabelModal';
|
|
24
|
+
const isDuplicateCaseLabelGraphQLError = (error) => {
|
|
25
|
+
var _a, _b, _c, _d;
|
|
26
|
+
if (!error || typeof error !== 'object') {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
const apolloError = error;
|
|
30
|
+
const messages = [
|
|
31
|
+
...((_b = (_a = apolloError.graphQLErrors) === null || _a === void 0 ? void 0 : _a.map((graphQLError) => graphQLError.message || '')) !== null && _b !== void 0 ? _b : []),
|
|
32
|
+
...((_d = (_c = apolloError.errors) === null || _c === void 0 ? void 0 : _c.map((graphQLError) => graphQLError.message || '')) !== null && _d !== void 0 ? _d : []),
|
|
33
|
+
apolloError.message || '',
|
|
34
|
+
]
|
|
35
|
+
.join(' ')
|
|
36
|
+
.toLowerCase();
|
|
37
|
+
return messages.includes('duplicate value found');
|
|
38
|
+
};
|
|
39
|
+
export function ManageCaseLabelsTab() {
|
|
40
|
+
var _a;
|
|
41
|
+
const { t } = useTranslation();
|
|
42
|
+
const history = useHistory();
|
|
43
|
+
const confirmation = useConfirmation();
|
|
44
|
+
const { globalMetadataState: { loggedInUsersAccount, loggedInUserRights }, } = useGlobalStateContext();
|
|
45
|
+
const accountId = (_a = loggedInUsersAccount === null || loggedInUsersAccount === void 0 ? void 0 : loggedInUsersAccount.data) === null || _a === void 0 ? void 0 : _a.salesforceAccountId;
|
|
46
|
+
const canManageCaseLabels = loggedInUserRights.data.isOrgAdmin();
|
|
47
|
+
const { labels: fetchedLabels, loading: isFetchingLabels, error: labelsError, refetch } = useCaseLabels(accountId);
|
|
48
|
+
const { createCaseLabel, loading: isCreatingLabel } = useCreateCaseLabel();
|
|
49
|
+
const { updateCaseLabel, loading: isUpdatingLabel } = useUpdateCaseLabel();
|
|
50
|
+
const { deleteCaseLabel } = useDeleteCaseLabel();
|
|
51
|
+
const [labels, setLabels] = useState([]);
|
|
52
|
+
const [searchString, setSearchString] = useState('');
|
|
53
|
+
const [isModalOpen, setIsModalOpen] = useState(false);
|
|
54
|
+
const [isInAddMode, setIsInAddMode] = useState(true);
|
|
55
|
+
const [selectedLabel, setSelectedLabel] = useState(null);
|
|
56
|
+
useEffect(() => {
|
|
57
|
+
setLabels(fetchedLabels);
|
|
58
|
+
}, [fetchedLabels]);
|
|
59
|
+
const filteredLabels = useMemo(() => {
|
|
60
|
+
if (isEmpty(searchString)) {
|
|
61
|
+
return labels;
|
|
62
|
+
}
|
|
63
|
+
return labels.filter((label) => label.name.toLowerCase().includes(searchString.toLowerCase()));
|
|
64
|
+
}, [labels, searchString]);
|
|
65
|
+
const hasNoLabels = !isFetchingLabels && !labelsError && labels.length === 0;
|
|
66
|
+
const onOpenAddModal = () => {
|
|
67
|
+
setIsInAddMode(true);
|
|
68
|
+
setSelectedLabel(null);
|
|
69
|
+
setIsModalOpen(true);
|
|
70
|
+
};
|
|
71
|
+
const onOpenEditModal = (label) => {
|
|
72
|
+
setIsInAddMode(false);
|
|
73
|
+
setSelectedLabel(label);
|
|
74
|
+
setIsModalOpen(true);
|
|
75
|
+
};
|
|
76
|
+
const closeModal = () => {
|
|
77
|
+
setIsModalOpen(false);
|
|
78
|
+
setSelectedLabel(null);
|
|
79
|
+
setIsInAddMode(true);
|
|
80
|
+
};
|
|
81
|
+
const onSaveLabel = (name, options) => __awaiter(this, void 0, void 0, function* () {
|
|
82
|
+
if (isInAddMode) {
|
|
83
|
+
if (!accountId) {
|
|
84
|
+
ToastNotification.addDangerMessage(t('Unable to create case label. Account information is missing.'));
|
|
85
|
+
return { success: false };
|
|
86
|
+
}
|
|
87
|
+
try {
|
|
88
|
+
yield createCaseLabel(name, accountId);
|
|
89
|
+
yield refetch();
|
|
90
|
+
ToastNotification.addSuccessMessage(t('Case label has been successfully created.'));
|
|
91
|
+
if (!(options === null || options === void 0 ? void 0 : options.keepOpen)) {
|
|
92
|
+
closeModal();
|
|
93
|
+
}
|
|
94
|
+
return { success: true };
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
if (isDuplicateCaseLabelGraphQLError(error)) {
|
|
98
|
+
return {
|
|
99
|
+
success: false,
|
|
100
|
+
fieldError: t('Label name already in use. Try a different name.'),
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
ToastNotification.addDangerMessage(t('Case label failed to create.'));
|
|
104
|
+
return { success: false };
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
if (selectedLabel) {
|
|
108
|
+
try {
|
|
109
|
+
yield updateCaseLabel(selectedLabel.id, name);
|
|
110
|
+
yield refetch();
|
|
111
|
+
ToastNotification.addSuccessMessage(t('Case label has been successfully updated.'));
|
|
112
|
+
closeModal();
|
|
113
|
+
return { success: true };
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
if (isDuplicateCaseLabelGraphQLError(error)) {
|
|
117
|
+
return {
|
|
118
|
+
success: false,
|
|
119
|
+
fieldError: t('Label name already in use. Try a different name.'),
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
ToastNotification.addDangerMessage(t('Case label failed to update.'));
|
|
123
|
+
return { success: false };
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return { success: false };
|
|
127
|
+
});
|
|
128
|
+
const onDeleteLabel = (label) => __awaiter(this, void 0, void 0, function* () {
|
|
129
|
+
try {
|
|
130
|
+
yield confirmation({
|
|
131
|
+
catchOnCancel: true,
|
|
132
|
+
confirmText: t('Delete label'),
|
|
133
|
+
confirmButtonVariant: ButtonVariant.danger,
|
|
134
|
+
cancelText: t('Cancel'),
|
|
135
|
+
modalVariant: ModalVariant.large,
|
|
136
|
+
title: t('Delete case label'),
|
|
137
|
+
description: (React.createElement("div", { className: "case-label-delete-description", style: { display: 'flex', flexDirection: 'column', gap: '1.5rem' } },
|
|
138
|
+
React.createElement("div", null, t('Are you sure you want to delete "{{name}}" case label?', { name: label.name })),
|
|
139
|
+
React.createElement("div", { style: { whiteSpace: 'nowrap' } },
|
|
140
|
+
t('This label is currently assigned to'),
|
|
141
|
+
' ',
|
|
142
|
+
React.createElement("strong", null, t('{{count}} cases', { count: label.assignedCaseCount })),
|
|
143
|
+
'. ',
|
|
144
|
+
t('Deleting it will remove the label from all associated cases.')))),
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
catch (_a) {
|
|
148
|
+
// user cancelled
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
try {
|
|
152
|
+
yield deleteCaseLabel(label.id);
|
|
153
|
+
yield refetch();
|
|
154
|
+
ToastNotification.addSuccessMessage(t('Case label has been successfully removed.'));
|
|
155
|
+
}
|
|
156
|
+
catch (_b) {
|
|
157
|
+
ToastNotification.addDangerMessage(t('Case label failed to remove.'));
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
const onViewAssignedCases = (label) => {
|
|
161
|
+
// Match Case List URL format (SolrQueryBuilder): caseLabel: ("<id>") orderBy lastModifiedDate desc
|
|
162
|
+
const query = `caseLabel: ("${label.id}") orderBy lastModifiedDate desc`;
|
|
163
|
+
history.push({
|
|
164
|
+
pathname: '/case/list',
|
|
165
|
+
search: getStringifiedParams({
|
|
166
|
+
query: encodeURIComponent(query),
|
|
167
|
+
searchType: 'basic',
|
|
168
|
+
}),
|
|
169
|
+
});
|
|
170
|
+
};
|
|
171
|
+
const columns = [
|
|
172
|
+
{
|
|
173
|
+
accessor: (label) => label.name,
|
|
174
|
+
sortable: false,
|
|
175
|
+
id: 'case-label-row',
|
|
176
|
+
title: '',
|
|
177
|
+
cellWidth: 100,
|
|
178
|
+
cell: (label) => (React.createElement("div", { className: "case-label-row" },
|
|
179
|
+
React.createElement("div", { className: "case-label-row__info" },
|
|
180
|
+
React.createElement("div", { className: "pf-v6-u-font-weight-bold" }, label.name),
|
|
181
|
+
React.createElement("div", { className: "pf-v6-u-color-200 pf-v6-u-font-size-sm" }, t('{{count}} cases assigned', { count: label.assignedCaseCount }))),
|
|
182
|
+
React.createElement("div", { className: "case-label-row__actions" },
|
|
183
|
+
label.assignedCaseCount > 0 && (React.createElement(Button, { variant: ButtonVariant.link, isInline: true, onClick: () => onViewAssignedCases(label), "data-tracking-id": "case-label-view-assigned-cases" },
|
|
184
|
+
React.createElement(Trans, null, "View assigned cases"))),
|
|
185
|
+
canManageCaseLabels && (React.createElement(ActionList, { isIconList: true },
|
|
186
|
+
React.createElement(ActionListItem, null,
|
|
187
|
+
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" })),
|
|
188
|
+
React.createElement(ActionListItem, null,
|
|
189
|
+
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" }))))))),
|
|
190
|
+
},
|
|
191
|
+
];
|
|
192
|
+
return (React.createElement(React.Fragment, null,
|
|
193
|
+
React.createElement("header", null,
|
|
194
|
+
React.createElement("h2", null, t('Case labels')),
|
|
195
|
+
React.createElement("p", null,
|
|
196
|
+
React.createElement(Trans, null, "Case labels help you organize and categorize cases with custom tags, making them easier to find, filter, and manage."))),
|
|
197
|
+
React.createElement("div", { className: "toolbar case-labels-toolbar" },
|
|
198
|
+
React.createElement("div", { className: "toolbar-left" },
|
|
199
|
+
hasNoLabels ? (React.createElement("span", null,
|
|
200
|
+
React.createElement(Trans, null, "Case labels"))) : (React.createElement("label", { htmlFor: "search-case-label-input" },
|
|
201
|
+
React.createElement(Trans, null, "Case labels"))),
|
|
202
|
+
!hasNoLabels && (React.createElement(React.Fragment, null,
|
|
203
|
+
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('') }),
|
|
204
|
+
canManageCaseLabels && (React.createElement("span", { className: "pf-v6-u-ml-sm" },
|
|
205
|
+
React.createElement(Button, { variant: ButtonVariant.primary, isInline: true, onClick: onOpenAddModal, "data-tracking-id": "case-label-add-button" },
|
|
206
|
+
React.createElement(Trans, null, "Add"))))))),
|
|
207
|
+
!hasNoLabels && (React.createElement("div", { className: "toolbar-right case-labels-toolbar__loaded pf-v6-u-color-200" }, t('{{loaded}} of {{total}} loaded.', {
|
|
208
|
+
loaded: filteredLabels.length,
|
|
209
|
+
total: filteredLabels.length,
|
|
210
|
+
})))),
|
|
211
|
+
React.createElement(AddEditCaseLabelModal, { isOpen: isModalOpen, addMode: isInAddMode, label: selectedLabel, isSaving: isCreatingLabel || isUpdatingLabel, onClose: closeModal, onSave: onSaveLabel }),
|
|
212
|
+
React.createElement(ErrorBoundary, { errorMsgInfo: { message: t('There was an error loading case labels list') } }, hasNoLabels ? (React.createElement("div", { className: "table-wrapper case-labels-empty-state" },
|
|
213
|
+
React.createElement(EmptyState, { headingLevel: "h2", icon: CubesIcon, titleText: canManageCaseLabels ? t('Create your first case label') : t('No case labels available'), variant: EmptyStateVariant.lg },
|
|
214
|
+
React.createElement(EmptyStateBody, null, canManageCaseLabels ? (React.createElement(Trans, null, "Case labels help you organize and categorize cases with custom tags, making them easier to find, filter, and manage.")) : (React.createElement(Trans, null, "Your organization admin hasn't created any labels yet. Contact them to add labels for organizing and categorizing cases."))),
|
|
215
|
+
canManageCaseLabels && (React.createElement(EmptyStateFooter, null,
|
|
216
|
+
React.createElement(Button, { variant: ButtonVariant.link, onClick: onOpenAddModal, "data-tracking-id": "case-label-empty-create-button" },
|
|
217
|
+
React.createElement(Trans, null, "Create label"))))))) : (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"), noResultText: canManageCaseLabels
|
|
218
|
+
? t('There are no results to display. Try adding a case label or refining your search')
|
|
219
|
+
: t('There are no results to display. Try refining your search') })))));
|
|
220
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/ManageCaseLabels/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './ManageCaseLabelsTab';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/components/ManageCaseLabels/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,iBAAiB,EAAE,MAAM,CAAC;CAC7B"}
|