@rh-support/manage 2.1.94 → 2.1.96

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 (50) hide show
  1. package/lib/esm/ManageTabs.d.ts.map +1 -1
  2. package/lib/esm/ManageTabs.js +11 -1
  3. package/lib/esm/Routes.d.ts +1 -0
  4. package/lib/esm/Routes.d.ts.map +1 -1
  5. package/lib/esm/Routes.js +6 -0
  6. package/lib/esm/components/ManageBookmarkedAccountsTab/BookmarkAccountSelector.d.ts.map +1 -1
  7. package/lib/esm/components/ManageBookmarkedAccountsTab/BookmarkAccountSelector.js +6 -1
  8. package/lib/esm/components/ManageExpiredContents/ExpiredContentCategory.d.ts +9 -0
  9. package/lib/esm/components/ManageExpiredContents/ExpiredContentCategory.d.ts.map +1 -0
  10. package/lib/esm/components/ManageExpiredContents/ExpiredContentCategory.js +18 -0
  11. package/lib/esm/components/ManageExpiredContents/ExpiredContentHeader.d.ts +3 -0
  12. package/lib/esm/components/ManageExpiredContents/ExpiredContentHeader.d.ts.map +1 -0
  13. package/lib/esm/components/ManageExpiredContents/ExpiredContentHeader.js +9 -0
  14. package/lib/esm/components/ManageExpiredContents/ExpiredContentManagement.d.ts +3 -0
  15. package/lib/esm/components/ManageExpiredContents/ExpiredContentManagement.d.ts.map +1 -0
  16. package/lib/esm/components/ManageExpiredContents/ExpiredContentManagement.js +13 -0
  17. package/lib/esm/components/ManageExpiredContents/ExpiredContentManager.d.ts +3 -0
  18. package/lib/esm/components/ManageExpiredContents/ExpiredContentManager.d.ts.map +1 -0
  19. package/lib/esm/components/ManageExpiredContents/ExpiredContentManager.js +70 -0
  20. package/lib/esm/components/ManageExpiredContents/ExpiredContentSingleItem.d.ts +9 -0
  21. package/lib/esm/components/ManageExpiredContents/ExpiredContentSingleItem.d.ts.map +1 -0
  22. package/lib/esm/components/ManageExpiredContents/ExpiredContentSingleItem.js +77 -0
  23. package/lib/esm/components/ManageExpiredContents/ExpiredContentSingleItemView.d.ts +14 -0
  24. package/lib/esm/components/ManageExpiredContents/ExpiredContentSingleItemView.d.ts.map +1 -0
  25. package/lib/esm/components/ManageExpiredContents/ExpiredContentSingleItemView.js +141 -0
  26. package/lib/esm/components/ManageExpiredContents/index.d.ts +2 -0
  27. package/lib/esm/components/ManageExpiredContents/index.d.ts.map +1 -0
  28. package/lib/esm/components/ManageExpiredContents/index.js +1 -0
  29. package/lib/esm/components/ManageTags/TagsManager.d.ts.map +1 -1
  30. package/lib/esm/components/ManageTags/TagsManager.js +20 -7
  31. package/lib/esm/components/TopContentManagement/TopContentEditor/TopContentCategoryContent/TopContentSingleItem.d.ts +2 -0
  32. package/lib/esm/components/TopContentManagement/TopContentEditor/TopContentCategoryContent/TopContentSingleItem.d.ts.map +1 -1
  33. package/lib/esm/components/TopContentManagement/TopContentEditor/TopContentCategoryContent/TopContentSingleItem.js +75 -20
  34. package/lib/esm/components/TopContentManagement/TopContentEditor/TopContentEditor.d.ts.map +1 -1
  35. package/lib/esm/components/TopContentManagement/TopContentEditor/TopContentEditor.js +7 -5
  36. package/lib/esm/context/ExpiredContentContextProvider.d.ts +8 -0
  37. package/lib/esm/context/ExpiredContentContextProvider.d.ts.map +1 -0
  38. package/lib/esm/context/ExpiredContentContextProvider.js +10 -0
  39. package/lib/esm/context/TopContentProvider.d.ts.map +1 -1
  40. package/lib/esm/context/TopContentProvider.js +1 -0
  41. package/lib/esm/index.d.ts +1 -0
  42. package/lib/esm/index.d.ts.map +1 -1
  43. package/lib/esm/index.js +1 -0
  44. package/lib/esm/reducers/ExpiredContentReducer.d.ts +35 -0
  45. package/lib/esm/reducers/ExpiredContentReducer.d.ts.map +1 -0
  46. package/lib/esm/reducers/ExpiredContentReducer.js +190 -0
  47. package/lib/esm/reducers/TopContentReducer.d.ts +5 -1
  48. package/lib/esm/reducers/TopContentReducer.d.ts.map +1 -1
  49. package/lib/esm/reducers/TopContentReducer.js +23 -7
  50. package/package.json +8 -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;AAalE,UAAU,MAAM;IACZ,UAAU,EAAE,mBAAmB,CAAC,EAAE,CAAC,CAAC;IACpC,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,qBA0LvC"}
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,qBAqMvC"}
@@ -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 { ExpiredContentManagement } from './components/ManageExpiredContents/ExpiredContentManagement';
11
12
  import { ManagePartnerships } from './components/ManagePartnerships/index';
12
13
  import { ManagePreferences } from './components/ManagePreferences';
13
14
  import { TagsManagement } from './components/ManageTags';
@@ -20,7 +21,7 @@ export function ManageTabs(props) {
20
21
  const [activeTabKey, setActiveTabKey] = useState(0);
21
22
  const { activeTab } = useParams();
22
23
  const { t } = useTranslation();
23
- const { groupsRoute, bookmarkedAccountsRoute, topContentRoute, notificationEmailsRoute, preferencesRoute, configsRoute, partnershipsRoute, tagsManagerRoute, } = Routes.getPaths();
24
+ const { groupsRoute, bookmarkedAccountsRoute, topContentRoute, notificationEmailsRoute, preferencesRoute, configsRoute, partnershipsRoute, tagsManagerRoute, expiredContentRoute, } = Routes.getPaths();
24
25
  useDocumentTitle(PageTitle.MANAGE);
25
26
  const canViewManageTab = ability.can(resourceActions.READ, resources.MANAGE);
26
27
  const canViewManageTopContent = ability.can(resourceActions.READ, resources.TOP_CONTENT) && canViewManageTab;
@@ -85,6 +86,15 @@ export function ManageTabs(props) {
85
86
  component: React.createElement(TopContentManagement, null),
86
87
  id: 'manage-top-content',
87
88
  });
89
+ canViewManageTopContent &&
90
+ tabsToRender.push({
91
+ title: 'Expired Content',
92
+ key: 'expired-content-tab',
93
+ 'data-tracking-id': 'manage-expired-content-tab',
94
+ routePath: expiredContentRoute,
95
+ id: 'manage-expired-content',
96
+ component: React.createElement(ExpiredContentManagement, null),
97
+ });
88
98
  canViewManageTopContent &&
89
99
  tabsToRender.push({
90
100
  title: 'Tags Manager',
@@ -13,6 +13,7 @@ interface ManageRoutes {
13
13
  groups: Route;
14
14
  savedSearches: Route;
15
15
  topContent: Route;
16
+ expiredContent: Route;
16
17
  tagsManager: Route;
17
18
  preferences: Route;
18
19
  notificationEmails: Route;
@@ -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,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,YA+EpB,CAAC"}
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,YAqFpB,CAAC"}
package/lib/esm/Routes.js CHANGED
@@ -30,6 +30,12 @@ export const Routes = {
30
30
  return getPath(this);
31
31
  },
32
32
  },
33
+ expiredContent: {
34
+ path: 'expired-content',
35
+ getPath() {
36
+ return getPath(this);
37
+ },
38
+ },
33
39
  tagsManager: {
34
40
  path: 'tags-manager',
35
41
  getPath() {
@@ -1 +1 @@
1
- {"version":3,"file":"BookmarkAccountSelector.d.ts","sourceRoot":"","sources":["../../../../src/components/ManageBookmarkedAccountsTab/BookmarkAccountSelector.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,4CAA4C,CAAC;AAIhF,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAOtD,OAAO,KAAsC,MAAM,OAAO,CAAC;AAG3D,UAAU,MAAM;IACZ,uBAAuB,EAAE,SAAS,EAAE,CAAC;IACrC,iBAAiB,CAAC,EAAE,kBAAkB,CAAC;IACvC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,yBAAyB,CAAC,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,KAAK,IAAI,CAAC;IAC5D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,SAAS,EAAE,CAAC;IAC9B,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,qBA0PpD;yBA1Pe,uBAAuB"}
1
+ {"version":3,"file":"BookmarkAccountSelector.d.ts","sourceRoot":"","sources":["../../../../src/components/ManageBookmarkedAccountsTab/BookmarkAccountSelector.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,4CAA4C,CAAC;AAIhF,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAQtD,OAAO,KAAsC,MAAM,OAAO,CAAC;AAG3D,UAAU,MAAM;IACZ,uBAAuB,EAAE,SAAS,EAAE,CAAC;IACrC,iBAAiB,CAAC,EAAE,kBAAkB,CAAC;IACvC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,yBAAyB,CAAC,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,KAAK,IAAI,CAAC;IAC5D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,SAAS,EAAE,CAAC;IAC9B,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,qBA6PpD;yBA7Pe,uBAAuB"}
@@ -11,6 +11,7 @@ import { accounts } from '@cee-eng/hydrajs';
11
11
  import { Label, LabelGroup, Tooltip } from '@patternfly/react-core';
12
12
  import { Select, SelectOption, SelectVariant } from '@patternfly/react-core/deprecated';
13
13
  import InfoCircleIcon from '@patternfly/react-icons/dist/js/icons/info-circle-icon';
14
+ import { sortAccountsByQuery } from '@rh-support/react-context/src/utils/utils';
14
15
  import assign from 'lodash/assign';
15
16
  import compact from 'lodash/compact';
16
17
  import debounce from 'lodash/debounce';
@@ -41,12 +42,15 @@ export function BookmarkAccountSelector(props) {
41
42
  limit: 60,
42
43
  accountNumberNotNull: true,
43
44
  };
45
+ let queryKey;
44
46
  // query as number is a hack to get around TS, isNaN can take a string but it was throwing error here
45
47
  if (isNaN(query)) {
46
48
  params.nameLike = query;
49
+ queryKey = 'name';
47
50
  }
48
51
  else {
49
52
  params.accountNumberLike = query;
53
+ queryKey = 'accountNumber';
50
54
  }
51
55
  const queryParams = !isEmpty(props.accountListParams)
52
56
  ? assign({}, props.accountListParams, params)
@@ -67,7 +71,8 @@ export function BookmarkAccountSelector(props) {
67
71
  return bookmarksMatch.length > 0
68
72
  ? Object.assign(Object.assign({}, account), { bookmarkGroupName: acountGroups, isBookmarked: true, isBookmarkedAndHasGroup: acountGroups.length > 0 }) : Object.assign(Object.assign({}, account), { bookmarkGroupName: [], isBookmarked: false, isBookmarkedAndHasGroup: false });
69
73
  });
70
- setOptions(accountsResponse);
74
+ const sortedOptions = sortAccountsByQuery(accountsResponse, query, queryKey);
75
+ setOptions(sortedOptions);
71
76
  setIsSearching(false);
72
77
  }
73
78
  catch (err) {
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import { IExpiredContentEditState } from '../../reducers/ExpiredContentReducer';
3
+ interface IProps {
4
+ category: IExpiredContentEditState;
5
+ isCategoryExpanded?: boolean;
6
+ }
7
+ export default function ExpiredContentCategory({ category, isCategoryExpanded }: IProps): React.JSX.Element;
8
+ export {};
9
+ //# sourceMappingURL=ExpiredContentCategory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExpiredContentCategory.d.ts","sourceRoot":"","sources":["../../../../src/components/ManageExpiredContents/ExpiredContentCategory.tsx"],"names":[],"mappings":"AACA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAEnD,OAAO,EAAE,wBAAwB,EAAE,MAAM,sCAAsC,CAAC;AAGhF,UAAU,MAAM;IACZ,QAAQ,EAAE,wBAAwB,CAAC;IACnC,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED,MAAM,CAAC,OAAO,UAAU,sBAAsB,CAAC,EAAE,QAAQ,EAAE,kBAA0B,EAAE,EAAE,MAAM,qBA0B9F"}
@@ -0,0 +1,18 @@
1
+ import { AccordionContent, AccordionItem, AccordionToggle } from '@patternfly/react-core';
2
+ import React, { useEffect, useState } from 'react';
3
+ import ExpiredContentSingleItem from './ExpiredContentSingleItem';
4
+ export default function ExpiredContentCategory({ category, isCategoryExpanded = false }) {
5
+ const [isExpanded, setIsExpanded] = useState(isCategoryExpanded);
6
+ const toggleExpanded = () => {
7
+ setIsExpanded((pre) => !pre);
8
+ };
9
+ useEffect(() => {
10
+ isCategoryExpanded !== isExpanded && setIsExpanded(isCategoryExpanded);
11
+ // eslint-disable-next-line react-hooks/exhaustive-deps
12
+ }, [isCategoryExpanded]);
13
+ return (React.createElement(AccordionItem, null,
14
+ React.createElement(AccordionToggle, { id: category.categoryName, onClick: toggleExpanded, isExpanded: isExpanded },
15
+ React.createElement("h3", null, category.categoryName)),
16
+ React.createElement(AccordionContent, { isHidden: !isExpanded },
17
+ React.createElement("ul", { className: "list-flat list-flushleft" }, category.content.map((content, i) => (React.createElement(ExpiredContentSingleItem, { key: content.topContentId, content: content, category: category })))))));
18
+ }
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ export default function ExpiredContentHeader(): React.JSX.Element;
3
+ //# sourceMappingURL=ExpiredContentHeader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExpiredContentHeader.d.ts","sourceRoot":"","sources":["../../../../src/components/ManageExpiredContents/ExpiredContentHeader.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,MAAM,CAAC,OAAO,UAAU,oBAAoB,sBAW3C"}
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import { Trans } from 'react-i18next';
3
+ export default function ExpiredContentHeader() {
4
+ return (React.createElement("header", null,
5
+ React.createElement("h2", null,
6
+ React.createElement(Trans, null, "Outdated Content")),
7
+ React.createElement("p", { className: "pf-v5-u-mt-md pf-v5-u-mb-sm" },
8
+ React.createElement(Trans, null))));
9
+ }
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ export declare function ExpiredContentManagement(): React.JSX.Element;
3
+ //# sourceMappingURL=ExpiredContentManagement.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExpiredContentManagement.d.ts","sourceRoot":"","sources":["../../../../src/components/ManageExpiredContents/ExpiredContentManagement.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAO1B,wBAAgB,wBAAwB,sBAWvC"}
@@ -0,0 +1,13 @@
1
+ import { ErrorBoundary } from '@rh-support/components';
2
+ import React from 'react';
3
+ import { useTranslation } from 'react-i18next';
4
+ import { ExpiredContentContextProvider } from '../../context/ExpiredContentContextProvider';
5
+ import { TagManagementContextProvider } from '../../context/TagManagementContextProvider';
6
+ import ExipredContentManager from './ExpiredContentManager';
7
+ export function ExpiredContentManagement() {
8
+ const { t } = useTranslation();
9
+ return (React.createElement(ErrorBoundary, { errorMsgInfo: { message: t('There was an error loading contents') } },
10
+ React.createElement(TagManagementContextProvider, null,
11
+ React.createElement(ExpiredContentContextProvider, null,
12
+ React.createElement(ExipredContentManager, null)))));
13
+ }
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ export default function ExipredContentManager(): React.JSX.Element;
3
+ //# sourceMappingURL=ExpiredContentManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExpiredContentManager.d.ts","sourceRoot":"","sources":["../../../../src/components/ManageExpiredContents/ExpiredContentManager.tsx"],"names":[],"mappings":"AAeA,OAAO,KAA2D,MAAM,OAAO,CAAC;AAUhF,MAAM,CAAC,OAAO,UAAU,qBAAqB,sBAoH5C"}
@@ -0,0 +1,70 @@
1
+ import { Accordion, Bullseye, EmptyState, EmptyStateBody, EmptyStateHeader, EmptyStateIcon, EmptyStateVariant, Spinner, Switch, } from '@patternfly/react-core';
2
+ import SearchIcon from '@patternfly/react-icons/dist/js/icons/search-icon';
3
+ import { TagsSelector, TopContentSearch } from '@rh-support/components';
4
+ import isEmpty from 'lodash/isEmpty';
5
+ import React, { useContext, useEffect, useMemo, useRef, useState } from 'react';
6
+ import { Trans, useTranslation } from 'react-i18next';
7
+ import { ExpiredContentDispatchContext, ExpiredContentStateContext } from '../../context/ExpiredContentContextProvider';
8
+ import { TagManagementDispatchContext, TagManagementStateContext } from '../../context/TagManagementContextProvider';
9
+ import { fetchExpiredContent, setExpiredContentFilteredTags } from '../../reducers/ExpiredContentReducer';
10
+ import { fetchTopContentTags } from '../../reducers/TagManagmentReducer';
11
+ import ExpiredContentCategory from './ExpiredContentCategory';
12
+ import ExpiredContentHeader from './ExpiredContentHeader';
13
+ export default function ExipredContentManager() {
14
+ const expiredContentResultsRef = useRef(null);
15
+ const { t } = useTranslation();
16
+ const [showApprochingExpiry, setShowApprochingExpiry] = useState(false);
17
+ const { expiredContentEditState, expiredContentResponse, filteredTags } = useContext(ExpiredContentStateContext);
18
+ const { tags: availableTags } = useContext(TagManagementStateContext);
19
+ const dispatch = useContext(ExpiredContentDispatchContext);
20
+ const tagManagerDispatch = useContext(TagManagementDispatchContext);
21
+ const [contentFilteredByQuery, setContentFilteredByQuery] = useState(expiredContentEditState);
22
+ const [searchQuery, setSearchQuery] = useState('');
23
+ const onSearch = (searchTerm, searchResults) => {
24
+ setContentFilteredByQuery(searchResults);
25
+ };
26
+ const filteredEC = useMemo(() => {
27
+ if (isEmpty(filteredTags))
28
+ return contentFilteredByQuery;
29
+ const filteredTagsIds = filteredTags.map((tag) => tag.id);
30
+ //filter top contents on basis of tags
31
+ const filteredData = contentFilteredByQuery.flatMap((item) => {
32
+ const contents = item.content.filter((content) => (content.tags || []).some((tag) => filteredTagsIds.includes(tag.id)));
33
+ if (!isEmpty(contents))
34
+ return [Object.assign(Object.assign({}, item), { content: contents })];
35
+ return [];
36
+ });
37
+ return filteredData;
38
+ }, [contentFilteredByQuery, filteredTags]);
39
+ const handleChange = (_event, checked) => {
40
+ setShowApprochingExpiry(checked);
41
+ fetchExpiredContent(dispatch, checked);
42
+ };
43
+ const onTagFilterChange = (tags) => {
44
+ setExpiredContentFilteredTags(dispatch, tags);
45
+ };
46
+ useEffect(() => {
47
+ fetchExpiredContent(dispatch);
48
+ fetchTopContentTags(tagManagerDispatch, false);
49
+ // eslint-disable-next-line react-hooks/exhaustive-deps
50
+ }, []);
51
+ useEffect(() => {
52
+ setContentFilteredByQuery(expiredContentEditState);
53
+ }, [expiredContentEditState]);
54
+ return (React.createElement(React.Fragment, null,
55
+ React.createElement(ExpiredContentHeader, null),
56
+ React.createElement("div", { className: "toolbar" },
57
+ React.createElement(TopContentSearch, { dataTrackingId: "expired-content-filter-manage", topContentData: expiredContentEditState, onSearch: onSearch, topContentResultsWrapperRef: expiredContentResultsRef, className: "toolbar-content", isDisabled: expiredContentResponse.isFetching, searchQuery: searchQuery, setSearchQuery: setSearchQuery }),
58
+ React.createElement("div", { className: "toolbar-content pf-v5-u-ml-md" },
59
+ React.createElement("label", { htmlFor: 'tag-selector' },
60
+ React.createElement(Trans, null, "All tags")),
61
+ React.createElement(TagsSelector, { tagOptions: availableTags, onChange: onTagFilterChange, selectedTags: filteredTags, disabled: expiredContentResponse.isFetching })),
62
+ React.createElement("div", { className: "toolbar-content pf-v5-u-mt-md" },
63
+ React.createElement(Switch, { id: "content-approaching-expiry-", label: t('Show approaching expiry'), isChecked: showApprochingExpiry, onChange: handleChange }))),
64
+ React.createElement("div", { className: "expired-content-manage-wrapper pf-v5-u-pt-md", ref: expiredContentResultsRef }, expiredContentResponse.isFetching ? (React.createElement(Bullseye, null,
65
+ React.createElement(EmptyState, { variant: EmptyStateVariant.full },
66
+ React.createElement(Spinner, { size: "lg" })))) : isEmpty(filteredEC) ? (React.createElement(EmptyState, { variant: EmptyStateVariant.xs },
67
+ React.createElement(EmptyStateHeader, { titleText: React.createElement(Trans, null, "No contents found"), icon: React.createElement(EmptyStateIcon, { icon: SearchIcon }) }),
68
+ React.createElement(EmptyStateBody, null,
69
+ React.createElement(Trans, null, "There are no contents to display")))) : (React.createElement(Accordion, null, filteredEC.map((category, i) => (React.createElement(ExpiredContentCategory, { key: category.id, category: category, isCategoryExpanded: !isEmpty(searchQuery) || !isEmpty(filteredTags) }))))))));
70
+ }
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import { IExpiredContent, IExpiredContentEditState } from '../../reducers/ExpiredContentReducer';
3
+ interface IProps {
4
+ content: IExpiredContent;
5
+ category: IExpiredContentEditState;
6
+ }
7
+ export default function ExpiredContentSingleItem({ content, category }: IProps): React.JSX.Element;
8
+ export {};
9
+ //# sourceMappingURL=ExpiredContentSingleItem.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExpiredContentSingleItem.d.ts","sourceRoot":"","sources":["../../../../src/components/ManageExpiredContents/ExpiredContentSingleItem.tsx"],"names":[],"mappings":"AAIA,OAAO,KAA+B,MAAM,OAAO,CAAC;AAIpD,OAAO,EAEH,eAAe,EACf,wBAAwB,EAE3B,MAAM,sCAAsC,CAAC;AAG9C,UAAU,MAAM;IACZ,OAAO,EAAE,eAAe,CAAC;IACzB,QAAQ,EAAE,wBAAwB,CAAC;CACtC;AAED,MAAM,CAAC,OAAO,UAAU,wBAAwB,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,MAAM,qBA2G7E"}
@@ -0,0 +1,77 @@
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, Label } from '@patternfly/react-core';
11
+ import EditAltIcon from '@patternfly/react-icons/dist/js/icons/edit-alt-icon';
12
+ import { ToastNotification } from '@rh-support/components';
13
+ import { formatDate, isFutureDate } from '@rh-support/utils';
14
+ import React, { useContext, useState } from 'react';
15
+ import { useTranslation } from 'react-i18next';
16
+ import { ExpiredContentDispatchContext, ExpiredContentStateContext } from '../../context/ExpiredContentContextProvider';
17
+ import { deleteExpiredContent, updateExpiredContent, } from '../../reducers/ExpiredContentReducer';
18
+ import ExpiredContentSingleItemView from './ExpiredContentSingleItemView';
19
+ export default function ExpiredContentSingleItem({ content, category }) {
20
+ var _a, _b;
21
+ const { t } = useTranslation();
22
+ const { expiredContentEditState, filteredTags } = useContext(ExpiredContentStateContext);
23
+ const dispatch = useContext(ExpiredContentDispatchContext);
24
+ const [isPreview, setIsPreview] = useState(true);
25
+ const [isSaving, setIsSaving] = useState(false);
26
+ const [isDeleting, setIsDeleting] = useState(false);
27
+ const editToggle = () => {
28
+ setIsPreview(!isPreview);
29
+ };
30
+ const onSave = (updatedContent, deletedTags) => __awaiter(this, void 0, void 0, function* () {
31
+ try {
32
+ setIsSaving(true);
33
+ yield updateExpiredContent(dispatch, expiredContentEditState, category.categoryId, updatedContent, deletedTags);
34
+ editToggle();
35
+ ToastNotification.addSuccessMessage(t('Content updated successfully'));
36
+ }
37
+ catch (error) {
38
+ ToastNotification.addDangerMessage(t('There was an error updating content'));
39
+ }
40
+ finally {
41
+ setIsSaving(false);
42
+ }
43
+ });
44
+ const onDelete = () => __awaiter(this, void 0, void 0, function* () {
45
+ try {
46
+ setIsDeleting(true);
47
+ yield deleteExpiredContent(dispatch, expiredContentEditState, category.id, content.topContentId);
48
+ editToggle();
49
+ ToastNotification.addSuccessMessage(t('Content deleted successfully'));
50
+ }
51
+ catch (error) {
52
+ ToastNotification.addDangerMessage(t('There was an error deleting content'));
53
+ }
54
+ finally {
55
+ setIsDeleting(false);
56
+ }
57
+ });
58
+ const lastModifiedBy = t(`Last modified {{created}} by {{by}}`, {
59
+ created: formatDate(content.updatedOn || content.createdOn),
60
+ by: content.updatedBy || content.createdBy,
61
+ });
62
+ const expiredText = t(` ${isFutureDate(content.expiryDate) ? 'Expires' : 'Expired'} on {{expired}}`, {
63
+ expired: formatDate(content.expiryDate),
64
+ });
65
+ return (React.createElement(React.Fragment, null, isPreview ? (React.createElement("li", { className: `push-bottom-narrow` },
66
+ React.createElement("a", { className: 'pcm-manage-top-content', "data-tracking-id": "pcm-manage-top-content", href: content.contentUrl, target: "_blank", rel: "noopener noreferrer" }, content.contentTitle),
67
+ React.createElement(Button, { variant: "link", isInline: true, icon: React.createElement(EditAltIcon, null), onClick: editToggle, title: 'Edit', "data-tracking-id": "edit-expired-top-content" }),
68
+ React.createElement("div", null,
69
+ lastModifiedBy,
70
+ " | ",
71
+ expiredText,
72
+ " | ",
73
+ content.product,
74
+ " ", (_a = content.majorVersion) !== null && _a !== void 0 ? _a : '',
75
+ content.minorVersion ? `.${content.minorVersion}` : ''),
76
+ React.createElement("div", null, (_b = content.tags) === null || _b === void 0 ? void 0 : _b.map((tag) => (React.createElement(Label, { isCompact: true, className: "pf-v5-u-mr-xs pf-v5-u-mt-sm", key: tag.id, color: filteredTags.some((t) => t.id === tag.id) ? 'gold' : 'grey' }, tag.tagName)))))) : (React.createElement(ExpiredContentSingleItemView, { category: category, content: content, onCancel: editToggle, onSave: onSave, onDelete: onDelete, isDeleting: isDeleting, isSaving: isSaving }))));
77
+ }
@@ -0,0 +1,14 @@
1
+ import React from 'react';
2
+ import { IExpiredContent, IExpiredContentEditState } from '../../reducers/ExpiredContentReducer';
3
+ interface IProps {
4
+ content: IExpiredContent;
5
+ category: IExpiredContentEditState;
6
+ onCancel: () => void;
7
+ onSave: (updatedContent: any, deletedTags: any[]) => void;
8
+ onDelete: () => void;
9
+ isSaving?: boolean;
10
+ isDeleting?: boolean;
11
+ }
12
+ export default function ExpiredContentSingleItemView({ category, content, onCancel, onSave, onDelete, isSaving, isDeleting, }: IProps): React.JSX.Element;
13
+ export {};
14
+ //# sourceMappingURL=ExpiredContentSingleItemView.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExpiredContentSingleItemView.d.ts","sourceRoot":"","sources":["../../../../src/components/ManageExpiredContents/ExpiredContentSingleItemView.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAwC,MAAM,OAAO,CAAC;AAI7D,OAAO,EAAE,eAAe,EAAE,wBAAwB,EAAE,MAAM,sCAAsC,CAAC;AAIjG,UAAU,MAAM;IACZ,OAAO,EAAE,eAAe,CAAC;IACzB,QAAQ,EAAE,wBAAwB,CAAC;IACnC,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,MAAM,EAAE,CAAC,cAAc,EAAE,GAAG,EAAE,WAAW,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC;IAC1D,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,CAAC,OAAO,UAAU,4BAA4B,CAAC,EACjD,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,UAAU,GACb,EAAE,MAAM,qBAmNR"}
@@ -0,0 +1,141 @@
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, DatePicker, Flex, FlexItem, FormGroup, TextInput, ValidatedOptions } from '@patternfly/react-core';
11
+ import { TagsSelector, ToastNotification } from '@rh-support/components';
12
+ import { getDrupalResIdIfTypeFromUrl, getText, isValidDate, isValidUrl } from '@rh-support/utils';
13
+ import { isEqual } from 'lodash';
14
+ import differenceBy from 'lodash/differenceBy';
15
+ import isEmpty from 'lodash/isEmpty';
16
+ import React, { useContext, useMemo, useState } from 'react';
17
+ import { Trans, useTranslation } from 'react-i18next';
18
+ import { TagManagementStateContext } from '../../context/TagManagementContextProvider';
19
+ import { getTopContentUrl } from '../../reducers/TopContentHelpers';
20
+ import { getDocsFromUrl } from '../TopContentManagement/TopContentEditor/TopContentCategoryContent/TopContentSingleItem';
21
+ export default function ExpiredContentSingleItemView({ category, content, onCancel, onSave, onDelete, isSaving, isDeleting, }) {
22
+ var _a, _b;
23
+ const { t } = useTranslation();
24
+ const tagManagementEditState = useContext(TagManagementStateContext);
25
+ const { tags: tagOptions } = tagManagementEditState;
26
+ const [isFetchingSolrSearch, setIsFetchingSolrSearch] = useState(false);
27
+ const [localContentUrl, setLocalContentUrl] = useState(content.contentUrl);
28
+ const [localContentTitle, setLocalContentTitle] = useState(content.contentTitle);
29
+ const [localSelectedTags, setLocalSelectedTags] = useState(content.tags || []);
30
+ const [localExpiryDate, setLocalExpiryDate] = useState((content === null || content === void 0 ? void 0 : content.expiryDate) || '');
31
+ const [contentTitleIsValid, setContentTitleIsValid] = useState(true);
32
+ const [contentUrlIsValid, setContentUrlIsValid] = useState(true);
33
+ const oldTagsIds = useMemo(() => { var _a; return ((_a = content === null || content === void 0 ? void 0 : content.tags) === null || _a === void 0 ? void 0 : _a.map((t) => t.id)) || []; }, [content === null || content === void 0 ? void 0 : content.tags]);
34
+ const localTagsIds = useMemo(() => localSelectedTags === null || localSelectedTags === void 0 ? void 0 : localSelectedTags.map((t) => t.id), [localSelectedTags]);
35
+ const onSubmit = (e) => e.preventDefault();
36
+ const updateContentTitleFromUrl = (contentUrl) => __awaiter(this, void 0, void 0, function* () {
37
+ var _c, _d;
38
+ // throws toast warning and clears it after 4 seconds
39
+ const throwWarningMessage = () => {
40
+ const message = getText('Unable to automatically fetch title. Please enter manually');
41
+ ToastNotification.addWarningMessage(message, '', { autoClose: 4000 });
42
+ };
43
+ try {
44
+ const nodeId = getDrupalResIdIfTypeFromUrl(contentUrl);
45
+ if (!nodeId)
46
+ return;
47
+ const docs = yield getDocsFromUrl(contentUrl);
48
+ const contentTitle = ((_c = docs[0]) === null || _c === void 0 ? void 0 : _c.publishedTitle) || ((_d = docs[0]) === null || _d === void 0 ? void 0 : _d.allTitle);
49
+ if (docs.length > 0 && docs[0].id === nodeId + '' && contentTitle) {
50
+ setLocalContentTitle(contentTitle);
51
+ setContentTitleIsValid(true);
52
+ }
53
+ else {
54
+ throwWarningMessage();
55
+ }
56
+ }
57
+ catch (e) {
58
+ throwWarningMessage();
59
+ }
60
+ });
61
+ const onLocalContentUrlChange = () => __awaiter(this, void 0, void 0, function* () {
62
+ if (localContentUrl === content.contentUrl)
63
+ return;
64
+ setIsFetchingSolrSearch(true);
65
+ yield updateContentTitleFromUrl(localContentUrl);
66
+ setIsFetchingSolrSearch(false);
67
+ });
68
+ const checkDuplicateUrls = (url) => {
69
+ //
70
+ onLocalContentUrlChange();
71
+ };
72
+ const onContentUrlChange = (contentUrl, event) => __awaiter(this, void 0, void 0, function* () {
73
+ setContentUrlIsValid(isValidUrl(contentUrl));
74
+ checkDuplicateUrls(contentUrl);
75
+ setLocalContentUrl(contentUrl);
76
+ });
77
+ const onContentTitleChange = (contentTitle, event) => {
78
+ const contentTitleIsValid = event.target.validity.valid;
79
+ setContentTitleIsValid(contentTitleIsValid);
80
+ setLocalContentTitle(contentTitle);
81
+ };
82
+ const handleLocalTagChange = (tags) => {
83
+ setLocalSelectedTags(tags);
84
+ };
85
+ const onExpiryDateChange = (event, str, date) => {
86
+ setLocalExpiryDate(str);
87
+ };
88
+ const expiryDateValidator = (date) => {
89
+ if (date < new Date())
90
+ return t('Invalid expiry date');
91
+ return '';
92
+ };
93
+ const onContentSave = () => {
94
+ const newTags = differenceBy(localTagsIds, oldTagsIds);
95
+ const deletedTags = differenceBy(oldTagsIds, localTagsIds);
96
+ const updatedContent = Object.assign(Object.assign({}, content), { contentTitle: localContentTitle, contentUrl: localContentUrl, tagList: newTags, tags: localSelectedTags.map((t) => ({ id: t.id, tagName: t.tagName })), expiryDate: localExpiryDate });
97
+ onSave(updatedContent, deletedTags);
98
+ };
99
+ const doesInputHasSpaces = isEmpty(localContentTitle.trim());
100
+ const isSaveButtonDisabled = doesInputHasSpaces ||
101
+ !(contentTitleIsValid &&
102
+ contentUrlIsValid &&
103
+ localContentTitle &&
104
+ localContentUrl &&
105
+ ((isValidDate(localExpiryDate) && isEmpty(expiryDateValidator(new Date(localExpiryDate)))) ||
106
+ (isEmpty(localExpiryDate) && isEmpty((_a = content.expiryDate) !== null && _a !== void 0 ? _a : '')))) ||
107
+ (localContentUrl === content.contentUrl &&
108
+ localContentTitle === content.contentTitle &&
109
+ isEqual(localTagsIds, oldTagsIds) &&
110
+ isEqual(localExpiryDate.split('T')[0], ((_b = content.expiryDate) === null || _b === void 0 ? void 0 : _b.split('T')[0]) || ''));
111
+ return (React.createElement("form", { noValidate: true, onSubmit: onSubmit, className: "card card-light push-bottom" },
112
+ React.createElement("div", { className: "form-group" },
113
+ React.createElement("label", { htmlFor: localContentTitle },
114
+ "Heading",
115
+ ' ',
116
+ React.createElement("span", { className: "form-required", "aria-hidden": true }, "*")),
117
+ React.createElement(TextInput, { isRequired: true, type: "text", maxLength: 254, required: true, value: localContentTitle, isDisabled: isFetchingSolrSearch, "aria-label": t('Copy and paste the heading for consistency'), placeholder: t('Copy and paste the heading for consistency'), onChange: (e, v) => onContentTitleChange(v, e), validated: contentTitleIsValid ? ValidatedOptions.default : ValidatedOptions.error })),
118
+ React.createElement("div", { className: "form-group" },
119
+ React.createElement("label", { htmlFor: localContentUrl },
120
+ "Link to content",
121
+ ' ',
122
+ React.createElement("span", { className: "form-required", "aria-hidden": true }, "*")),
123
+ React.createElement(TextInput, { type: "url", maxLength: 254, isRequired: true, pattern: "^(http(s)?:\\/\\/)+[\\w\\-\\._~:\\/?#[\\]@!\\$&'\\(\\)\\*\\+,;=.]+$", value: getTopContentUrl(localContentUrl), "aria-label": t('Entering a solution or article link first will automatically generate the heading for you'), placeholder: t('Entering a solution or article link first will automatically generate the heading for you'), onChange: (evt, val) => onContentUrlChange(val, evt), validated: contentUrlIsValid ? ValidatedOptions.default : ValidatedOptions.error })),
124
+ React.createElement(Flex, { className: "pf-v5-u-my-lg" },
125
+ React.createElement(FlexItem, { flex: { default: 'flex_1' } },
126
+ React.createElement(FormGroup, { label: t('Tags') },
127
+ React.createElement("div", { className: "pf-v5-c-form-control" },
128
+ React.createElement(TagsSelector, { tagOptions: tagOptions, onChange: handleLocalTagChange, selectedTags: localSelectedTags, placeholder: t('Select tags to improve discoverability') })))),
129
+ React.createElement(FlexItem, null,
130
+ React.createElement(FormGroup, { label: t('Expiry date') },
131
+ React.createElement(DatePicker, { onBlur: onExpiryDateChange, onChange: onExpiryDateChange, value: !isEmpty(localExpiryDate) ? localExpiryDate.split('T')[0] : '', validators: [expiryDateValidator] })))),
132
+ React.createElement("span", { className: "top-content-single-item-footer" },
133
+ React.createElement("span", null,
134
+ React.createElement(Button, { variant: "primary", onClick: onContentSave, isDisabled: isSaveButtonDisabled || isSaving, isLoading: isSaving },
135
+ React.createElement(Trans, null, "Save")),
136
+ ' ',
137
+ React.createElement(Button, { variant: "tertiary", onClick: onCancel, "data-tracking-id": "cancel-button-top-content" },
138
+ React.createElement(Trans, null, "Cancel"))),
139
+ React.createElement("span", { className: "content-actions" },
140
+ React.createElement(Button, { variant: "danger", "aria-label": t('Delete content'), onClick: onDelete, isDisabled: isDeleting }, "Delete")))));
141
+ }
@@ -0,0 +1,2 @@
1
+ export { ExpiredContentManagement } from './ExpiredContentManagement';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/ManageExpiredContents/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC"}
@@ -0,0 +1 @@
1
+ export { ExpiredContentManagement } from './ExpiredContentManagement';
@@ -1 +1 @@
1
- {"version":3,"file":"TagsManager.d.ts","sourceRoot":"","sources":["../../../../src/components/ManageTags/TagsManager.tsx"],"names":[],"mappings":"AAyBA,OAAO,KAAmD,MAAM,OAAO,CAAC;AAOxE,MAAM,CAAC,OAAO,UAAU,WAAW,sBAuXlC"}
1
+ {"version":3,"file":"TagsManager.d.ts","sourceRoot":"","sources":["../../../../src/components/ManageTags/TagsManager.tsx"],"names":[],"mappings":"AA6BA,OAAO,KAAmD,MAAM,OAAO,CAAC;AAOxE,MAAM,CAAC,OAAO,UAAU,WAAW,sBAuYlC"}
@@ -7,8 +7,10 @@ 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 { ActionList, ActionListItem, Bullseye, Button, ButtonVariant, EmptyState, EmptyStateVariant, Flex, FormGroup, FormHelperText, HelperText, HelperTextItem, Modal, SearchInput, Spinner, TextInput, } from '@patternfly/react-core';
10
+ import { ActionList, ActionListItem, Bullseye, Button, ButtonVariant, EmptyState, EmptyStateVariant, Flex, FormGroup, FormHelperText, HelperText, HelperTextItem, Modal, Spinner, TextInput, TextInputGroup, TextInputGroupMain, TextInputGroupUtilities, } from '@patternfly/react-core';
11
11
  import PencilAltIcon from '@patternfly/react-icons/dist/js/icons/pencil-alt-icon';
12
+ import SearchIcon from '@patternfly/react-icons/dist/js/icons/search-icon';
13
+ import TimesIcon from '@patternfly/react-icons/dist/js/icons/times-icon';
12
14
  import TrashIcon from '@patternfly/react-icons/dist/js/icons/trash-icon';
13
15
  import { ErrorBoundary, ToastNotification } from '@rh-support/components';
14
16
  import { formatDate } from '@rh-support/utils';
@@ -78,6 +80,7 @@ export default function TagsManager() {
78
80
  try {
79
81
  setIsCreatingNewTag(true);
80
82
  yield createNewTags(dispatch, [{ tagName: newTagName.trim(), isActive: true }]);
83
+ setTagSearchTerm('');
81
84
  ToastNotification.addSuccessMessage(t('Successfully created tag'));
82
85
  }
83
86
  catch (err) {
@@ -86,10 +89,10 @@ export default function TagsManager() {
86
89
  }
87
90
  finally {
88
91
  setIsCreatingNewTag(false);
89
- onCanceCreateNewTag();
92
+ onCancelCreateNewTag();
90
93
  }
91
94
  });
92
- const onCanceCreateNewTag = () => {
95
+ const onCancelCreateNewTag = () => {
93
96
  setCreateTagError('');
94
97
  setCreateTagModalOpen(false);
95
98
  setNewTagName('');
@@ -149,6 +152,9 @@ export default function TagsManager() {
149
152
  setSelectedDeleteTag(null);
150
153
  }
151
154
  });
155
+ const onSearchClear = () => {
156
+ setTagSearchTerm('');
157
+ };
152
158
  const columns = [
153
159
  {
154
160
  accessor: (id) => tagsByIds[id].tagName,
@@ -192,10 +198,10 @@ export default function TagsManager() {
192
198
  React.createElement(TrashIcon, null))))),
193
199
  },
194
200
  ];
195
- const CreateTagModel = (React.createElement(Modal, { title: t('Create a tag'), onClose: onCanceCreateNewTag, isOpen: createTagModalOpen, actions: [
201
+ const CreateTagModel = (React.createElement(Modal, { title: t('Create a tag'), onClose: onCancelCreateNewTag, isOpen: createTagModalOpen, actions: [
196
202
  React.createElement(Button, { key: "create-tag", variant: ButtonVariant.primary, onClick: onCreateNewTag, isLoading: isCreatingNewTag, isDisabled: !isEmpty(createTagError) || isCreatingNewTag },
197
203
  React.createElement(Trans, null, "Create")),
198
- React.createElement(Button, { key: "cancel-create-tag", variant: ButtonVariant.link, onClick: onCanceCreateNewTag }, "Cancel"),
204
+ React.createElement(Button, { key: "cancel-create-tag", variant: ButtonVariant.link, onClick: onCancelCreateNewTag }, "Cancel"),
199
205
  ] },
200
206
  React.createElement(FormGroup, { label: "Tag name", isRequired: true },
201
207
  React.createElement(TextInput, { isRequired: true, type: "text", id: "create-new-tag-text-input", value: newTagName, onChange: (e, v) => {
@@ -237,9 +243,16 @@ export default function TagsManager() {
237
243
  React.createElement("label", { htmlFor: "tag-search-input" },
238
244
  React.createElement(Trans, null, "Search Tag")),
239
245
  React.createElement("div", { className: "pf-v5-u-flex-grow-1" },
240
- React.createElement(SearchInput, { type: "text", id: "tag-search-input", value: tagSearchTerm, onChange: (e, v) => setTagSearchTerm(v), placeholder: t('Search for a tag') })),
246
+ React.createElement(TextInputGroup, null,
247
+ React.createElement(TextInputGroupMain, { type: "text", id: "tag-search-input", placeholder: t('Search for a tag'), icon: React.createElement(SearchIcon, null), value: tagSearchTerm, onChange: (e, v) => setTagSearchTerm(v) }),
248
+ React.createElement(TextInputGroupUtilities, null,
249
+ React.createElement(Button, { variant: "plain", onClick: onSearchClear, "aria-label": "Clear button and input" },
250
+ React.createElement(TimesIcon, null))))),
241
251
  React.createElement("span", { className: "pf-v5-u-ml-sm" },
242
- React.createElement(Button, { variant: ButtonVariant.primary, isInline: true, onClick: () => setCreateTagModalOpen(true), "data-tracking-id": "tag-create-button" },
252
+ React.createElement(Button, { variant: ButtonVariant.primary, isInline: true, onClick: () => {
253
+ setCreateTagModalOpen(true);
254
+ setNewTagName(tagSearchTerm);
255
+ }, "data-tracking-id": "tag-create-button" },
243
256
  React.createElement(Trans, null, "Create tag"))))),
244
257
  React.createElement("div", { className: "tags-manager-wrapper" },
245
258
  React.createElement(ErrorBoundary, { errorMsgInfo: { message: t('There was an error loading tags list') } }, tagResponse.isFetching ? (React.createElement(Bullseye, null,