@rh-support/cases 2.6.227 → 2.6.229

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 (171) hide show
  1. package/lib/esm/components/case/NewCaseButton.js +1 -1
  2. package/lib/esm/components/case-list/CaseList.d.ts +0 -7
  3. package/lib/esm/components/case-list/CaseList.d.ts.map +1 -1
  4. package/lib/esm/components/case-list/CaseList.js +368 -137
  5. package/lib/esm/components/case-list/CaseListContext.d.ts.map +1 -1
  6. package/lib/esm/components/case-list/CaseListContext.js +5 -2
  7. package/lib/esm/components/case-list/CaseListFilterContext.d.ts.map +1 -1
  8. package/lib/esm/components/case-list/CaseListFilterContext.js +2 -1
  9. package/lib/esm/components/case-list/CaseListFilterHelpers.d.ts +3 -2
  10. package/lib/esm/components/case-list/CaseListFilterHelpers.d.ts.map +1 -1
  11. package/lib/esm/components/case-list/CaseListFilterHelpers.js +19 -6
  12. package/lib/esm/components/case-list/CaseListFilterReducer.d.ts +36 -4
  13. package/lib/esm/components/case-list/CaseListFilterReducer.d.ts.map +1 -1
  14. package/lib/esm/components/case-list/CaseListFilterReducer.js +6 -12
  15. package/lib/esm/components/case-list/CaseListReducer.d.ts +22 -10
  16. package/lib/esm/components/case-list/CaseListReducer.d.ts.map +1 -1
  17. package/lib/esm/components/case-list/CaseListReducer.js +25 -7
  18. package/lib/esm/components/case-list/case-list-filters/AccountsFilter.d.ts.map +1 -1
  19. package/lib/esm/components/case-list/case-list-filters/AccountsFilter.js +18 -11
  20. package/lib/esm/components/case-list/case-list-filters/AdditionalFilters.d.ts.map +1 -1
  21. package/lib/esm/components/case-list/case-list-filters/AdditionalFilters.js +6 -2
  22. package/lib/esm/components/case-list/case-list-filters/CaseLabelsFilter.d.ts +3 -0
  23. package/lib/esm/components/case-list/case-list-filters/CaseLabelsFilter.d.ts.map +1 -0
  24. package/lib/esm/components/case-list/case-list-filters/CaseLabelsFilter.js +177 -0
  25. package/lib/esm/components/case-list/case-list-filters/CaseListFilterChips.d.ts +1 -7
  26. package/lib/esm/components/case-list/case-list-filters/CaseListFilterChips.d.ts.map +1 -1
  27. package/lib/esm/components/case-list/case-list-filters/CaseListFilterChips.js +12 -16
  28. package/lib/esm/components/case-list/case-list-filters/CaseListFilters.d.ts +2 -5
  29. package/lib/esm/components/case-list/case-list-filters/CaseListFilters.d.ts.map +1 -1
  30. package/lib/esm/components/case-list/case-list-filters/CaseListFilters.js +14 -13
  31. package/lib/esm/components/case-list/case-list-filters/CreatorSsoNameFilter.d.ts.map +1 -1
  32. package/lib/esm/components/case-list/case-list-filters/CreatorSsoNameFilter.js +21 -14
  33. package/lib/esm/components/case-list/case-list-filters/CreatorSsoNameFilterChip.d.ts.map +1 -1
  34. package/lib/esm/components/case-list/case-list-filters/CreatorSsoNameFilterChip.js +3 -0
  35. package/lib/esm/components/case-list/case-list-filters/GroupsFilter.d.ts +11 -1
  36. package/lib/esm/components/case-list/case-list-filters/GroupsFilter.d.ts.map +1 -1
  37. package/lib/esm/components/case-list/case-list-filters/GroupsFilter.js +90 -70
  38. package/lib/esm/components/case-list/case-list-filters/ProductFilterChip.d.ts +1 -3
  39. package/lib/esm/components/case-list/case-list-filters/ProductFilterChip.d.ts.map +1 -1
  40. package/lib/esm/components/case-list/case-list-filters/ProductFilterChip.js +2 -2
  41. package/lib/esm/components/case-list/case-list-filters/ProductsFilter.d.ts +5 -4
  42. package/lib/esm/components/case-list/case-list-filters/ProductsFilter.d.ts.map +1 -1
  43. package/lib/esm/components/case-list/case-list-filters/ProductsFilter.js +15 -54
  44. package/lib/esm/components/case-list/case-list-filters/SeverityFilter.d.ts +0 -3
  45. package/lib/esm/components/case-list/case-list-filters/SeverityFilter.d.ts.map +1 -1
  46. package/lib/esm/components/case-list/case-list-filters/SeverityFilter.js +18 -44
  47. package/lib/esm/components/case-list/case-list-filters/StatusFilter.d.ts +0 -3
  48. package/lib/esm/components/case-list/case-list-filters/StatusFilter.d.ts.map +1 -1
  49. package/lib/esm/components/case-list/case-list-filters/StatusFilter.js +14 -44
  50. package/lib/esm/components/case-list/case-list-filters/VersionsFilter.d.ts +1 -3
  51. package/lib/esm/components/case-list/case-list-filters/VersionsFilter.d.ts.map +1 -1
  52. package/lib/esm/components/case-list/case-list-filters/VersionsFilter.js +60 -59
  53. package/lib/esm/components/case-list/case-list-table/ArchivedCaseLabel.d.ts +3 -0
  54. package/lib/esm/components/case-list/case-list-table/ArchivedCaseLabel.d.ts.map +1 -0
  55. package/lib/esm/components/case-list/case-list-table/ArchivedCaseLabel.js +8 -0
  56. package/lib/esm/components/case-list/case-list-table/CaseListLabelGroup.d.ts +9 -0
  57. package/lib/esm/components/case-list/case-list-table/CaseListLabelGroup.d.ts.map +1 -0
  58. package/lib/esm/components/case-list/case-list-table/CaseListLabelGroup.js +105 -0
  59. package/lib/esm/components/case-list/case-list-table/CaseListTable.d.ts +8 -3
  60. package/lib/esm/components/case-list/case-list-table/CaseListTable.d.ts.map +1 -1
  61. package/lib/esm/components/case-list/case-list-table/CaseListTable.js +87 -84
  62. package/lib/esm/components/case-list/case-list-table/CaseListTableRow.d.ts +33 -0
  63. package/lib/esm/components/case-list/case-list-table/CaseListTableRow.d.ts.map +1 -0
  64. package/lib/esm/components/case-list/case-list-table/CaseListTableRow.js +51 -0
  65. package/lib/esm/components/case-list/case-list-table/CaseListTableSkeletonRow.d.ts +9 -0
  66. package/lib/esm/components/case-list/case-list-table/CaseListTableSkeletonRow.d.ts.map +1 -0
  67. package/lib/esm/components/case-list/case-list-table/CaseListTableSkeletonRow.js +10 -0
  68. package/lib/esm/components/case-list/case-list-table/DownloadCSVFileModal.d.ts +0 -5
  69. package/lib/esm/components/case-list/case-list-table/DownloadCSVFileModal.d.ts.map +1 -1
  70. package/lib/esm/components/case-list/case-list-table/DownloadCSVFileModal.js +51 -70
  71. package/lib/esm/components/case-list/case-list-table/ExportCaseListCSV.d.ts.map +1 -1
  72. package/lib/esm/components/case-list/case-list-table/ExportCaseListCSV.js +5 -15
  73. package/lib/esm/components/case-list/case-list-table/SeverityLabel.js +1 -1
  74. package/lib/esm/components/case-list/case-list-table/TableActionsDropdown.d.ts.map +1 -1
  75. package/lib/esm/components/case-list/case-list-table/TableActionsDropdown.js +2 -3
  76. package/lib/esm/components/case-list/case-list-table/table-column-selector/TableColumnSelector.d.ts.map +1 -1
  77. package/lib/esm/components/case-list/case-list-table/table-column-selector/TableColumnSelector.js +1 -0
  78. package/lib/esm/components/case-list/case-search/AdvanceSearchToggleButton.d.ts +8 -0
  79. package/lib/esm/components/case-list/case-search/AdvanceSearchToggleButton.d.ts.map +1 -0
  80. package/lib/esm/components/case-list/case-search/AdvanceSearchToggleButton.js +8 -0
  81. package/lib/esm/components/case-list/case-search/BookmarkedSearchesSelector.d.ts.map +1 -1
  82. package/lib/esm/components/case-list/case-search/BookmarkedSearchesSelector.js +1 -0
  83. package/lib/esm/components/case-list/case-search/CaseSearch.d.ts.map +1 -1
  84. package/lib/esm/components/case-list/case-search/CaseSearch.js +55 -24
  85. package/lib/esm/components/case-list/case-search/advance-search-modal/AdvanceSearchAccountSection.d.ts +10 -0
  86. package/lib/esm/components/case-list/case-search/advance-search-modal/AdvanceSearchAccountSection.d.ts.map +1 -0
  87. package/lib/esm/components/case-list/case-search/advance-search-modal/AdvanceSearchAccountSection.js +29 -0
  88. package/lib/esm/components/case-list/case-search/advance-search-modal/AdvanceSearchAuditsSection.d.ts +10 -0
  89. package/lib/esm/components/case-list/case-search/advance-search-modal/AdvanceSearchAuditsSection.d.ts.map +1 -0
  90. package/lib/esm/components/case-list/case-search/advance-search-modal/AdvanceSearchAuditsSection.js +16 -0
  91. package/lib/esm/components/case-list/case-search/advance-search-modal/AdvanceSearchCaseSection.d.ts +9 -0
  92. package/lib/esm/components/case-list/case-search/advance-search-modal/AdvanceSearchCaseSection.d.ts.map +1 -0
  93. package/lib/esm/components/case-list/case-search/advance-search-modal/AdvanceSearchCaseSection.js +21 -0
  94. package/lib/esm/components/case-list/case-search/advance-search-modal/AdvanceSearchDateRangeField.d.ts +12 -0
  95. package/lib/esm/components/case-list/case-search/advance-search-modal/AdvanceSearchDateRangeField.d.ts.map +1 -0
  96. package/lib/esm/components/case-list/case-search/advance-search-modal/AdvanceSearchDateRangeField.js +31 -0
  97. package/lib/esm/components/case-list/case-search/advance-search-modal/AdvanceSearchFieldBlock.d.ts +10 -0
  98. package/lib/esm/components/case-list/case-search/advance-search-modal/AdvanceSearchFieldBlock.d.ts.map +1 -0
  99. package/lib/esm/components/case-list/case-search/advance-search-modal/AdvanceSearchFieldBlock.js +10 -0
  100. package/lib/esm/components/case-list/case-search/advance-search-modal/AdvanceSearchModal.d.ts +10 -0
  101. package/lib/esm/components/case-list/case-search/advance-search-modal/AdvanceSearchModal.d.ts.map +1 -0
  102. package/lib/esm/components/case-list/case-search/advance-search-modal/AdvanceSearchModal.js +92 -0
  103. package/lib/esm/components/case-list/case-search/advance-search-modal/AdvanceSearchOwnerSection.d.ts +9 -0
  104. package/lib/esm/components/case-list/case-search/advance-search-modal/AdvanceSearchOwnerSection.d.ts.map +1 -0
  105. package/lib/esm/components/case-list/case-search/advance-search-modal/AdvanceSearchOwnerSection.js +20 -0
  106. package/lib/esm/components/case-list/case-search/advance-search-modal/AdvanceSearchProductSection.d.ts +9 -0
  107. package/lib/esm/components/case-list/case-search/advance-search-modal/AdvanceSearchProductSection.d.ts.map +1 -0
  108. package/lib/esm/components/case-list/case-search/advance-search-modal/AdvanceSearchProductSection.js +28 -0
  109. package/lib/esm/components/case-list/case-search/advance-search-modal/ProductVersionDrilldownSelect.d.ts +9 -0
  110. package/lib/esm/components/case-list/case-search/advance-search-modal/ProductVersionDrilldownSelect.d.ts.map +1 -0
  111. package/lib/esm/components/case-list/case-search/advance-search-modal/ProductVersionDrilldownSelect.js +241 -0
  112. package/lib/esm/components/case-list/case-search/advance-search-modal/SelectableLabelFilter.d.ts +11 -0
  113. package/lib/esm/components/case-list/case-search/advance-search-modal/SelectableLabelFilter.d.ts.map +1 -0
  114. package/lib/esm/components/case-list/case-search/advance-search-modal/SelectableLabelFilter.js +23 -0
  115. package/lib/esm/components/case-list/case-search/useAdvanceSearchParser.d.ts.map +1 -1
  116. package/lib/esm/components/case-list/case-search/useAdvanceSearchParser.js +2 -1
  117. package/lib/esm/css/caseList.css +183 -22
  118. package/lib/esm/css/caseSearch.css +114 -0
  119. package/lib/esm/enums/case.d.ts +13 -5
  120. package/lib/esm/enums/case.d.ts.map +1 -1
  121. package/lib/esm/enums/case.js +23 -3
  122. package/lib/esm/enums/caseSearch.d.ts +3 -0
  123. package/lib/esm/enums/caseSearch.d.ts.map +1 -1
  124. package/lib/esm/enums/caseSearch.js +2 -1
  125. package/lib/esm/enums/filters.d.ts +3 -1
  126. package/lib/esm/enums/filters.d.ts.map +1 -1
  127. package/lib/esm/enums/filters.js +2 -0
  128. package/lib/esm/hooks/useCaseLabels.d.ts +14 -0
  129. package/lib/esm/hooks/useCaseLabels.d.ts.map +1 -0
  130. package/lib/esm/hooks/useCaseLabels.js +56 -0
  131. package/lib/esm/hooks/useCloseCase.d.ts.map +1 -1
  132. package/lib/esm/hooks/useCloseCase.js +38 -21
  133. package/lib/esm/hooks/useExportCaseListCSV.d.ts.map +1 -1
  134. package/lib/esm/hooks/useExportCaseListCSV.js +1 -9
  135. package/lib/esm/hooks/useFilterStateOnLoad.d.ts +1 -1
  136. package/lib/esm/hooks/useFilterStateOnLoad.d.ts.map +1 -1
  137. package/lib/esm/hooks/useFilterStateOnLoad.js +7 -5
  138. package/lib/esm/index.js +1 -0
  139. package/lib/esm/models/caseList.d.ts +1 -0
  140. package/lib/esm/models/caseList.d.ts.map +1 -1
  141. package/lib/esm/test-utils/mockData.d.ts +1 -0
  142. package/lib/esm/test-utils/mockData.d.ts.map +1 -1
  143. package/lib/esm/test-utils/mockData.js +2 -1
  144. package/lib/esm/utils/advanceSearchFormMapper.d.ts +11 -0
  145. package/lib/esm/utils/advanceSearchFormMapper.d.ts.map +1 -0
  146. package/lib/esm/utils/advanceSearchFormMapper.js +71 -0
  147. package/lib/esm/utils/advanceSearchUtils.d.ts +24 -0
  148. package/lib/esm/utils/advanceSearchUtils.d.ts.map +1 -0
  149. package/lib/esm/utils/advanceSearchUtils.js +150 -0
  150. package/lib/esm/utils/caseGroupDefaultFilterUtils.d.ts +12 -0
  151. package/lib/esm/utils/caseGroupDefaultFilterUtils.d.ts.map +1 -0
  152. package/lib/esm/utils/caseGroupDefaultFilterUtils.js +34 -0
  153. package/lib/esm/utils/caseGroupDefaultUtils.d.ts +10 -0
  154. package/lib/esm/utils/caseGroupDefaultUtils.d.ts.map +1 -0
  155. package/lib/esm/utils/caseGroupDefaultUtils.js +20 -0
  156. package/lib/esm/utils/caseListGraphQLUtils.d.ts +28 -0
  157. package/lib/esm/utils/caseListGraphQLUtils.d.ts.map +1 -0
  158. package/lib/esm/utils/caseListGraphQLUtils.js +280 -0
  159. package/lib/esm/utils/caseListMapper.d.ts +6 -0
  160. package/lib/esm/utils/caseListMapper.d.ts.map +1 -0
  161. package/lib/esm/utils/caseListMapper.js +47 -0
  162. package/lib/esm/utils/caseListVariablesBuilder.d.ts +15 -0
  163. package/lib/esm/utils/caseListVariablesBuilder.d.ts.map +1 -0
  164. package/lib/esm/utils/caseListVariablesBuilder.js +526 -0
  165. package/lib/esm/utils/caseSearchUtils.d.ts.map +1 -1
  166. package/lib/esm/utils/caseSearchUtils.js +39 -2
  167. package/lib/esm/utils/constants.d.ts +5 -1
  168. package/lib/esm/utils/constants.d.ts.map +1 -1
  169. package/lib/esm/utils/constants.js +10 -2
  170. package/lib/esm/utils/mockSolrResponse.js +1 -1
  171. package/package.json +10 -8
@@ -9,124 +9,272 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  };
10
10
  import '../../css/caseList.css';
11
11
  import '../../css/caseSearch.css';
12
+ import { useApolloClient } from '@apollo/client/react';
12
13
  import { Alert, AlertActionCloseButton, AlertVariant, Button } from '@patternfly/react-core';
13
14
  import OpenDrawerRightIcon from '@patternfly/react-icons/dist/js/icons/open-drawer-right-icon';
14
- import { ErrorBoundary, ToastNotification, useBreakpoint, useDocumentTitle, useForceUpdate, usePrevious, } from '@rh-support/components';
15
- import { CSSUserModal, fetchAllStatuses, fetchCaseGroupsForAccount, fetchCaseGroupsForSSO, fetchCaseSeverities, fetchCaseTypes, fetchProducts, GlobalMetadataDispatchContext, GlobalMetadataStateContext, setUserPreferences, updateCaseListTraditionalSupportAgreed, updateUserPreferences, useGlobalDispatchContext, UserPreferencesKeys, } from '@rh-support/react-context';
16
- import { getStringifiedParams, getUrlParsedParams, haventLoadedMetadata, haventLoadedProductsMetadata, solrResponseToFacetFields, solrResponseToPivotFields, } from '@rh-support/utils';
17
- import get from 'lodash/get';
15
+ import { ErrorBoundary, ToastNotification, useBreakpoint, useDocumentTitle, useForceUpdate, } from '@rh-support/components';
16
+ import { CSSUserModal, fetchAllStatuses, fetchCaseGroupsForAccount, fetchCaseGroupsForSSO, fetchCaseSeverities, fetchCaseTypes, fetchProducts, GlobalMetadataDispatchContext, GlobalMetadataStateContext, setTraditionalSupportSessionAgreed, setUserPreferences, updateUserPreferences, useGlobalDispatchContext, UserPreferencesKeys, } from '@rh-support/react-context';
17
+ import { getStringifiedParams, getUrlParsedParams, haventLoadedMetadata, haventLoadedProductsMetadata, pendoTrackEvent, } from '@rh-support/utils';
18
18
  import isEmpty from 'lodash/isEmpty';
19
- import mapValues from 'lodash/mapValues';
19
+ import isEqual from 'lodash/isEqual';
20
20
  import some from 'lodash/some';
21
21
  import React, { useContext, useEffect, useRef, useState } from 'react';
22
22
  import { Trans, useTranslation } from 'react-i18next';
23
+ import { useInView } from 'react-intersection-observer';
23
24
  import { useLocation } from 'react-router-dom';
24
25
  import { CaseSearchQueryType } from '../../enums/caseSearch';
25
- import { SolrPivotKeys } from '../../enums/filters';
26
+ import { SolrKeys } from '../../enums/filters';
26
27
  import { PageTitle } from '../../enums/pageTitle';
27
28
  import { useFilterStateOnLoad } from '../../hooks/useFilterStateOnLoad';
28
- import { getCaseList } from '../../utils/caseListUtils';
29
+ import { getDefaultGroupFilterSelection, shouldApplyDefaultGroupFilter } from '../../utils/caseGroupDefaultFilterUtils';
30
+ import { clearPageCursors, getCaseListFromGraphQL, loadMoreCases, } from '../../utils/caseListGraphQLUtils';
29
31
  import { createFilterStateFromUrlQuery, createURLQueryFromFilterState, FILTER_URL_CURRENT_PAGE_SEARCH_PARAM, FILTER_URL_PAGE_SIZE_SEARCH_PARAM, FILTER_URL_QUERY_SEARCH_PARAM, FILTER_URL_QUERY_TYPE, } from '../../utils/caseSearchUtils';
32
+ import { UpdatedCaseDataEvent } from '../../utils/constants';
30
33
  import { NewCaseButton } from '../case/NewCaseButton';
31
34
  import { CaseListFilterChips } from './case-list-filters/CaseListFilterChips';
32
35
  import { CaseListFilters } from './case-list-filters/CaseListFilters';
33
36
  import { CaseListTable } from './case-list-table/CaseListTable';
34
37
  import { CaseSearch } from './case-search/CaseSearch';
35
38
  import { useCaseListDispatchContext, useCaseListStateContext } from './CaseListContext';
36
- import { CaseListFilterDispatchContext, CaseListFilterStateContext, initialCaseFilterState, } from './CaseListFilterContext';
37
- import { eligibleSFDCFiltersMultipleValues, isNoFilterApplied, isOnlyDefaultFilterApplied, } from './CaseListFilterHelpers';
39
+ import { CaseListFilterDispatchContext, CaseListFilterStateContext } from './CaseListFilterContext';
40
+ import { isNoFilterApplied, isOnlyDefaultFilterApplied, isOnlyGroupFilterApplied } from './CaseListFilterHelpers';
38
41
  import { updateFilterState } from './CaseListFilterReducer';
39
- import { setCaseList, setCurrentQuery, setFilterValuesFromFacetResponse, setIsFetching, setPivotValues, } from './CaseListReducer';
42
+ import { appendCaseList, setCaseList, setCurrentQuery, setCursorInfo, setIsFetching, setIsLoadingMore, setLoadMoreError, } from './CaseListReducer';
40
43
  export function CaseList(props) {
41
- var _a, _b;
44
+ var _a, _b, _c, _d, _e, _f, _g, _h;
42
45
  const { t } = useTranslation();
43
46
  useDocumentTitle(PageTitle.CASE_LIST);
44
47
  const dispatchToGlobalMetadataReducer = useContext(GlobalMetadataDispatchContext);
45
- const { caseList, pivotValues, isFetching, filterValuesFromFacetResponse, currentQuery } = useCaseListStateContext();
48
+ const { caseList, isFetching, isLoadingMore, hasNextPage, endCursor, currentQuery, loadMoreError, loadMoreRetryCount, } = useCaseListStateContext();
46
49
  const CaseListDispatch = useCaseListDispatchContext();
47
50
  const breakPoint = useBreakpoint();
48
- const { globalMetadataState, globalMetadataState: { caseGroups, loggedInUserJwtToken, loggedInUserRights, loggedInUsersAccount, userPreferences, managedAccounts, bookmarkedAccounts, allCaseTypes, allCaseSeverities, allCaseStatuses, allProducts, caseListTraditionalSupportAgreed, }, } = useContext(GlobalMetadataStateContext);
51
+ const { globalMetadataState, globalMetadataState: { caseGroups, loggedInUser, loggedInUserRights, loggedInUsersAccount, userPreferences, managedAccounts, bookmarkedAccounts, allCaseTypes, allCaseSeverities, allCaseStatuses, allProducts, caseRecordTypes, caseListTraditionalSupportAgreed, hydraUserPreferences, }, } = useContext(GlobalMetadataStateContext);
49
52
  const globalDispatchContext = useGlobalDispatchContext();
53
+ const apolloClient = useApolloClient();
54
+ const includeSecureSupportCases = Boolean(loggedInUsersAccount.data.secureSupport);
50
55
  const location = useLocation();
51
56
  const searchParams = getUrlParsedParams(location.search);
52
57
  const queryFromUrl = searchParams[FILTER_URL_QUERY_SEARCH_PARAM];
53
- const pageSizeFromUrl = parseInt(searchParams[FILTER_URL_PAGE_SIZE_SEARCH_PARAM]);
54
- const currentPageFromUrl = parseInt(searchParams[FILTER_URL_CURRENT_PAGE_SEARCH_PARAM]);
55
58
  const searchType = searchParams[FILTER_URL_QUERY_TYPE];
56
59
  const abortControllerRef = useRef(undefined);
60
+ const lastPushedQueryRef = useRef('');
57
61
  const isXLScreen = breakPoint.xl;
58
62
  const isFirstMount = useRef(true);
63
+ const userDismissedDefaultGroupRef = useRef(false);
64
+ const prevGroupFilterRef = useRef(undefined);
59
65
  const filterSectionRef = useRef(null);
60
66
  const filterState = useContext(CaseListFilterStateContext);
61
67
  const filterDispatch = useContext(CaseListFilterDispatchContext);
62
68
  const forceUpdate = useForceUpdate();
63
69
  const isCaseListFilterPanelExanded = userPreferences.data.isCaseListFilterPanelExanded;
64
70
  const useFilterStateInit = useFilterStateOnLoad();
65
- const isBasicSearchMode = filterState.filterQueryInfo.type === CaseSearchQueryType.BASIC ||
66
- (filterState.filterQueryInfo.type === CaseSearchQueryType.ADVANCED && loggedInUserRights.data.isExternal());
67
- const prevSearchType = usePrevious(filterState.filterQueryInfo.type);
68
- let isSearchTypeChanged = filterState.filterQueryInfo.type !== prevSearchType;
69
71
  const [hasError, setHasError] = useState(null);
70
- const [isSolrSearchDown, setSolrSearchDown] = useState(false);
71
72
  const [defaultSavedSearchName, setDefaultSavedSearchName] = useState('');
72
73
  const [RHCDValue, setRHCDValue] = useState('');
73
74
  const [isRHCDAlertShown, setIsRHCDAlertShown] = useState(true);
75
+ const loadMoreLockRef = useRef(false);
76
+ const loadMoreFnRef = useRef(() => { });
77
+ const loadMoreCooldownRef = useRef(false);
78
+ const loadMoreAbortRef = useRef(null);
79
+ const activeFilterStateRef = useRef(filterState);
80
+ const sentinelElRef = useRef(null);
81
+ const prefetchRef = useRef({
82
+ cursor: '',
83
+ data: null,
84
+ loading: false,
85
+ });
86
+ const { ref: inViewRef, inView } = useInView();
87
+ const sentinelRef = React.useCallback((node) => {
88
+ sentinelElRef.current = node || null;
89
+ inViewRef(node);
90
+ }, [inViewRef]);
91
+ function startPrefetch(cursor) {
92
+ if (!cursor || prefetchRef.current.cursor === cursor)
93
+ return;
94
+ prefetchRef.current = { cursor, data: null, loading: true };
95
+ loadMoreCases(activeFilterStateRef.current, apolloClient, cursor, undefined, includeSecureSupportCases)
96
+ .then((result) => {
97
+ if (prefetchRef.current.cursor === cursor) {
98
+ prefetchRef.current = { cursor, data: result, loading: false };
99
+ }
100
+ })
101
+ .catch(() => {
102
+ if (prefetchRef.current.cursor === cursor) {
103
+ prefetchRef.current = { cursor: '', data: null, loading: false };
104
+ }
105
+ });
106
+ }
107
+ useEffect(() => {
108
+ let ticking = false;
109
+ let triggered = false;
110
+ const onScroll = () => {
111
+ if (ticking)
112
+ return;
113
+ ticking = true;
114
+ requestAnimationFrame(() => {
115
+ ticking = false;
116
+ if (!sentinelElRef.current)
117
+ return;
118
+ const rect = sentinelElRef.current.getBoundingClientRect();
119
+ const isNear = rect.top <= window.innerHeight + 600;
120
+ if (!isNear) {
121
+ triggered = false;
122
+ return;
123
+ }
124
+ if (!triggered && !loadMoreLockRef.current) {
125
+ triggered = true;
126
+ loadMoreFnRef.current();
127
+ }
128
+ });
129
+ };
130
+ window.addEventListener('scroll', onScroll, true);
131
+ return () => window.removeEventListener('scroll', onScroll, true);
132
+ }, []);
133
+ useEffect(() => {
134
+ if (inView && hasNextPage && !isLoadingMore && !loadMoreError) {
135
+ loadMore();
136
+ }
137
+ // eslint-disable-next-line react-hooks/exhaustive-deps
138
+ }, [inView]);
139
+ useEffect(() => {
140
+ if (!isLoadingMore)
141
+ return;
142
+ const handleOffline = () => {
143
+ if (loadMoreAbortRef.current) {
144
+ loadMoreAbortRef.current.abort();
145
+ loadMoreAbortRef.current = null;
146
+ }
147
+ loadMoreLockRef.current = false;
148
+ setLoadMoreError(CaseListDispatch, true, loadMoreRetryCount + 1);
149
+ };
150
+ if (!navigator.onLine) {
151
+ handleOffline();
152
+ return;
153
+ }
154
+ window.addEventListener('offline', handleOffline);
155
+ return () => window.removeEventListener('offline', handleOffline);
156
+ // eslint-disable-next-line react-hooks/exhaustive-deps
157
+ }, [isLoadingMore]);
158
+ useEffect(() => {
159
+ const onClick = (e) => {
160
+ const anchor = e.target.closest('a.btn_slideto[href="#masthead"]');
161
+ if (anchor) {
162
+ e.preventDefault();
163
+ window.scrollTo({ top: 0, behavior: 'smooth' });
164
+ }
165
+ };
166
+ document.addEventListener('click', onClick, true);
167
+ return () => document.removeEventListener('click', onClick, true);
168
+ }, []);
74
169
  function getCases(currentFilterState) {
75
170
  return __awaiter(this, void 0, void 0, function* () {
76
- let showError;
171
+ var _a;
77
172
  try {
78
- setIsFetching(CaseListDispatch, true);
79
- setHasError(false);
80
- if (abortControllerRef.current !== undefined) {
81
- // Cancel the previous request
173
+ if (abortControllerRef.current) {
82
174
  abortControllerRef.current.abort();
83
175
  }
84
- // recreate a new AbortController for each call
85
- let controller = new AbortController();
176
+ const controller = new AbortController();
86
177
  abortControllerRef.current = controller;
87
- const { caseListResponse, isSolrSearchDownSFDCUp, showErrorMessage } = yield getCaseList(currentFilterState, loggedInUserRights.data, loggedInUsersAccount.data, controller.signal);
88
- showError = showErrorMessage;
89
- setSolrSearchDown(isSolrSearchDownSFDCUp);
90
- setFilterValuesFromFacetResponse(CaseListDispatch, solrResponseToFacetFields(caseListResponse));
91
- setPivotValues(CaseListDispatch, solrResponseToPivotFields(caseListResponse));
92
- setCaseList(CaseListDispatch, caseListResponse.response);
178
+ setIsFetching(CaseListDispatch, true);
179
+ setHasError(false);
180
+ prefetchRef.current = { cursor: '', data: null, loading: false };
181
+ loadMoreCooldownRef.current = true;
182
+ activeFilterStateRef.current = currentFilterState;
183
+ const result = yield getCaseListFromGraphQL(currentFilterState, apolloClient, undefined, controller.signal, undefined, includeSecureSupportCases);
184
+ if (controller.signal.aborted) {
185
+ return;
186
+ }
187
+ setCaseList(CaseListDispatch, result.caseListResponse.response);
188
+ setCursorInfo(CaseListDispatch, result.hasNextPage, result.endCursor);
93
189
  setIsFetching(CaseListDispatch, false);
190
+ setTimeout(() => {
191
+ loadMoreCooldownRef.current = false;
192
+ }, 500);
193
+ if (result.hasNextPage && result.endCursor) {
194
+ startPrefetch(result.endCursor);
195
+ }
196
+ if (result.showErrorMessage) {
197
+ setHasError(true);
198
+ ToastNotification.addDangerMessage(t('There was an error loading case data. Please try again.'));
199
+ }
94
200
  }
95
201
  catch (err) {
96
- const isAbortError = err.message && err.message.toLowerCase().indexOf('abort') > -1;
97
- if (!isAbortError) {
98
- setIsFetching(CaseListDispatch, false);
99
- setHasError(true);
100
- showError && ToastNotification.addXHRErrorMessage(err);
202
+ if ((err === null || err === void 0 ? void 0 : err.name) === 'AbortError' || ((_a = err === null || err === void 0 ? void 0 : err.message) === null || _a === void 0 ? void 0 : _a.includes('aborted'))) {
203
+ return;
101
204
  }
205
+ setIsFetching(CaseListDispatch, false);
206
+ setHasError(true);
207
+ ToastNotification.addXHRErrorMessage(err);
102
208
  }
103
209
  });
104
210
  }
211
+ function loadMore() {
212
+ return __awaiter(this, void 0, void 0, function* () {
213
+ var _a;
214
+ if (loadMoreCooldownRef.current ||
215
+ loadMoreLockRef.current ||
216
+ isLoadingMore ||
217
+ !hasNextPage ||
218
+ !endCursor ||
219
+ loadMoreError)
220
+ return;
221
+ loadMoreLockRef.current = true;
222
+ if (loadMoreAbortRef.current) {
223
+ loadMoreAbortRef.current.abort();
224
+ }
225
+ const controller = new AbortController();
226
+ loadMoreAbortRef.current = controller;
227
+ setIsLoadingMore(CaseListDispatch, true);
228
+ try {
229
+ let result;
230
+ const pf = prefetchRef.current;
231
+ if (pf.cursor === endCursor && pf.data) {
232
+ result = pf.data;
233
+ prefetchRef.current = { cursor: '', data: null, loading: false };
234
+ }
235
+ else {
236
+ prefetchRef.current = { cursor: '', data: null, loading: false };
237
+ result = yield loadMoreCases(activeFilterStateRef.current, apolloClient, endCursor, controller.signal, includeSecureSupportCases);
238
+ }
239
+ if (controller.signal.aborted)
240
+ return;
241
+ setLoadMoreError(CaseListDispatch, false, 0);
242
+ appendCaseList(CaseListDispatch, result.docs, result.hasNextPage, result.endCursor);
243
+ if (result.hasNextPage && result.endCursor) {
244
+ startPrefetch(result.endCursor);
245
+ }
246
+ }
247
+ catch (err) {
248
+ if ((err === null || err === void 0 ? void 0 : err.name) === 'AbortError' || ((_a = err === null || err === void 0 ? void 0 : err.message) === null || _a === void 0 ? void 0 : _a.includes('aborted')) || controller.signal.aborted) {
249
+ return;
250
+ }
251
+ const nextRetryCount = loadMoreRetryCount + 1;
252
+ setLoadMoreError(CaseListDispatch, true, nextRetryCount);
253
+ console.error('[CaseList] loadMore error:', err);
254
+ }
255
+ finally {
256
+ if (!controller.signal.aborted) {
257
+ loadMoreLockRef.current = false;
258
+ }
259
+ }
260
+ });
261
+ }
262
+ loadMoreFnRef.current = loadMore;
263
+ function retryLoadMore() {
264
+ if (loadMoreAbortRef.current) {
265
+ loadMoreAbortRef.current.abort();
266
+ loadMoreAbortRef.current = null;
267
+ }
268
+ loadMoreLockRef.current = false;
269
+ setLoadMoreError(CaseListDispatch, false, loadMoreRetryCount);
270
+ setTimeout(() => loadMoreFnRef.current(), 0);
271
+ }
105
272
  const toggleFilterSection = (isExpanded) => {
106
273
  if (!filterSectionRef.current)
107
274
  return;
108
275
  filterSectionRef.current.expanded = isExpanded;
109
276
  forceUpdate();
110
277
  };
111
- function saveFilterQueryInUserPreferences() {
112
- if (isNoFilterApplied(filterState))
113
- return;
114
- const type = filterState.filterQueryInfo.type;
115
- const recentSerach = {
116
- filterState: type === CaseSearchQueryType.BASIC ? filterState.filterInfo : {},
117
- sortState: filterState.sortInfo,
118
- queryString: type === CaseSearchQueryType.BASIC
119
- ? filterState.filterQueryInfo.queryString
120
- : filterState.filterQueryInfo.parsedQuery,
121
- type,
122
- };
123
- try {
124
- updateUserPreferences(dispatchToGlobalMetadataReducer, loggedInUserRights.data.getSSOUsername(), [{ key: UserPreferencesKeys.mostRecentSearch, value: JSON.stringify(recentSerach) }], 'add');
125
- }
126
- catch (e) {
127
- console.error('Could not save filter query in user preferences');
128
- }
129
- }
130
278
  const onToggleFilterBtnClick = () => {
131
279
  var _a, _b;
132
280
  toggleFilterSection(!((_a = filterSectionRef.current) === null || _a === void 0 ? void 0 : _a.expanded));
@@ -136,8 +284,7 @@ export function CaseList(props) {
136
284
  };
137
285
  const checkNewCases = () => __awaiter(this, void 0, void 0, function* () {
138
286
  try {
139
- const { caseListResponse, isSolrSearchDownSFDCUp } = yield getCaseList(filterState, loggedInUserRights.data, loggedInUsersAccount.data, null);
140
- setSolrSearchDown(isSolrSearchDownSFDCUp);
287
+ const { caseListResponse } = yield getCaseListFromGraphQL(filterState, apolloClient, undefined, undefined, undefined, includeSecureSupportCases);
141
288
  let changed = false;
142
289
  if (caseListResponse.response.numFound <= filterState.paginationInfo.pageSize &&
143
290
  caseListResponse.response.numFound !== caseList.numFound) {
@@ -159,6 +306,7 @@ export function CaseList(props) {
159
306
  }
160
307
  if (changed && location.pathname === '/case/list') {
161
308
  setCaseList(CaseListDispatch, caseListResponse.response);
309
+ pendoTrackEvent(UpdatedCaseDataEvent);
162
310
  ToastNotification.addSuccessMessage(t('Case data has been updated'));
163
311
  }
164
312
  }
@@ -166,79 +314,145 @@ export function CaseList(props) {
166
314
  console.log(err);
167
315
  }
168
316
  });
317
+ const salesforceAccountId = (_a = loggedInUsersAccount.data) === null || _a === void 0 ? void 0 : _a.salesforceAccountId;
318
+ const loggedInContactId = (_b = loggedInUser === null || loggedInUser === void 0 ? void 0 : loggedInUser.data) === null || _b === void 0 ? void 0 : _b.id;
319
+ const loggedInIsOrgAdmin = (_c = loggedInUser === null || loggedInUser === void 0 ? void 0 : loggedInUser.data) === null || _c === void 0 ? void 0 : _c.isOrgAdmin;
320
+ const defaultCaseGroupId = (_e = (_d = loggedInUser === null || loggedInUser === void 0 ? void 0 : loggedInUser.data) === null || _d === void 0 ? void 0 : _d.defaultCaseGroup) !== null && _e !== void 0 ? _e : null;
321
+ const prevDefaultCaseGroupIdRef = useRef(defaultCaseGroupId);
169
322
  useEffect(() => {
170
323
  var _a;
171
- if (haventLoadedMetadata(caseGroups, (data) => data === undefined)) {
172
- if ((_a = loggedInUsersAccount.data) === null || _a === void 0 ? void 0 : _a.isInternal) {
173
- fetchCaseGroupsForAccount(dispatchToGlobalMetadataReducer, loggedInUsersAccount.data.accountNumber);
174
- }
175
- else {
176
- fetchCaseGroupsForSSO(dispatchToGlobalMetadataReducer, loggedInUserJwtToken.preferred_username);
177
- }
324
+ if (prevDefaultCaseGroupIdRef.current !== defaultCaseGroupId) {
325
+ userDismissedDefaultGroupRef.current = false;
326
+ }
327
+ prevDefaultCaseGroupIdRef.current = defaultCaseGroupId;
328
+ const currentGroupFilter = ((_a = filterState.filterInfo) === null || _a === void 0 ? void 0 : _a[SolrKeys.group]) || [];
329
+ if (prevGroupFilterRef.current !== undefined &&
330
+ prevGroupFilterRef.current.length > 0 &&
331
+ currentGroupFilter.length === 0) {
332
+ userDismissedDefaultGroupRef.current = true;
178
333
  }
179
- }, [caseGroups, dispatchToGlobalMetadataReducer, loggedInUserJwtToken, loggedInUsersAccount.data]);
334
+ prevGroupFilterRef.current = currentGroupFilter;
335
+ }, [filterState.filterInfo, defaultCaseGroupId]);
180
336
  useEffect(() => {
181
- if (haventLoadedMetadata(allCaseTypes)) {
182
- fetchCaseTypes(dispatchToGlobalMetadataReducer, loggedInUsersAccount.data.secureSupport);
337
+ var _a;
338
+ if (!salesforceAccountId || loggedInUser.isFetching)
339
+ return;
340
+ if (!haventLoadedMetadata(caseGroups, (data) => data === undefined))
341
+ return;
342
+ if ((_a = loggedInUsersAccount.data) === null || _a === void 0 ? void 0 : _a.isInternal) {
343
+ fetchCaseGroupsForAccount(dispatchToGlobalMetadataReducer, apolloClient, salesforceAccountId, defaultCaseGroupId, loggedInContactId, loggedInIsOrgAdmin);
344
+ }
345
+ else {
346
+ fetchCaseGroupsForSSO(dispatchToGlobalMetadataReducer, apolloClient, salesforceAccountId, defaultCaseGroupId, loggedInContactId, loggedInIsOrgAdmin);
347
+ }
348
+ }, [
349
+ apolloClient,
350
+ caseGroups,
351
+ dispatchToGlobalMetadataReducer,
352
+ defaultCaseGroupId,
353
+ loggedInContactId,
354
+ loggedInIsOrgAdmin,
355
+ loggedInUser.isFetching,
356
+ (_f = loggedInUsersAccount.data) === null || _f === void 0 ? void 0 : _f.isInternal,
357
+ salesforceAccountId,
358
+ ]);
359
+ useEffect(() => {
360
+ if (location.pathname !== '/case/list')
361
+ return;
362
+ if (loggedInUser.isFetching || caseGroups.isFetching || caseGroups.data === undefined)
363
+ return;
364
+ if (!shouldApplyDefaultGroupFilter(queryFromUrl, hydraUserPreferences.data))
365
+ return;
366
+ const canAutoSync = isNoFilterApplied(filterState) ||
367
+ isOnlyDefaultFilterApplied(filterState) ||
368
+ isOnlyGroupFilterApplied(filterState.filterInfo);
369
+ if (!canAutoSync)
370
+ return;
371
+ const nextGroupFilter = getDefaultGroupFilterSelection(caseGroups.data, loggedInUser === null || loggedInUser === void 0 ? void 0 : loggedInUser.data);
372
+ const currentGroupFilter = filterState.filterInfo[SolrKeys.group] || [];
373
+ if (userDismissedDefaultGroupRef.current && currentGroupFilter.length === 0) {
374
+ return;
183
375
  }
184
- // when solr is down, we use hydra metadata api to populated filter dropdowns
185
- if (isSolrSearchDown) {
376
+ if (isEqual(currentGroupFilter, nextGroupFilter))
377
+ return;
378
+ updateFilterState(filterDispatch, Object.assign(Object.assign({}, filterState), { filterInfo: Object.assign(Object.assign({}, filterState.filterInfo), { [SolrKeys.group]: nextGroupFilter }) }));
379
+ // eslint-disable-next-line react-hooks/exhaustive-deps
380
+ }, [
381
+ defaultCaseGroupId,
382
+ caseGroups.data,
383
+ caseGroups.isFetching,
384
+ loggedInUser.isFetching,
385
+ location.pathname,
386
+ queryFromUrl,
387
+ ]);
388
+ useEffect(() => {
389
+ const loadMetadata = () => __awaiter(this, void 0, void 0, function* () {
390
+ if (haventLoadedMetadata(allCaseTypes)) {
391
+ fetchCaseTypes(dispatchToGlobalMetadataReducer, apolloClient);
392
+ }
186
393
  if (haventLoadedMetadata(allCaseSeverities)) {
187
- fetchCaseSeverities(dispatchToGlobalMetadataReducer, loggedInUsersAccount.data.secureSupport);
394
+ fetchCaseSeverities(dispatchToGlobalMetadataReducer, apolloClient);
188
395
  }
189
396
  if (haventLoadedMetadata(allCaseStatuses)) {
190
- fetchAllStatuses(dispatchToGlobalMetadataReducer, loggedInUsersAccount.data.secureSupport);
397
+ fetchAllStatuses(dispatchToGlobalMetadataReducer, apolloClient);
191
398
  }
192
399
  if (haventLoadedProductsMetadata(allProducts)) {
193
- fetchProducts(dispatchToGlobalMetadataReducer);
400
+ fetchProducts(dispatchToGlobalMetadataReducer, apolloClient);
194
401
  }
195
- // on sfdc fields that only one value is allowed, set filter to first item
196
- const sfdcFilterState = mapValues(filterState.filterInfo, (value, key) => {
197
- //@ts-ignore
198
- if (eligibleSFDCFiltersMultipleValues.includes(key))
199
- return value;
200
- return value[0] ? [value[0]] : [];
201
- });
202
- updateFilterState(filterDispatch, {
203
- //@ts-ignore
204
- filterInfo: Object.assign(Object.assign({}, initialCaseFilterState.filterInfo), sfdcFilterState),
205
- });
206
- }
402
+ });
403
+ loadMetadata();
207
404
  // eslint-disable-next-line react-hooks/exhaustive-deps
208
- }, [
209
- allCaseTypes,
210
- allCaseSeverities,
211
- allCaseStatuses,
212
- allProducts,
213
- dispatchToGlobalMetadataReducer,
214
- loggedInUsersAccount.data.secureSupport,
215
- isSolrSearchDown,
216
- ]);
405
+ }, [allCaseTypes, allCaseSeverities, allCaseStatuses, allProducts, dispatchToGlobalMetadataReducer, apolloClient]);
406
+ function saveFilterQueryInUserPreferences() {
407
+ if (isNoFilterApplied(filterState))
408
+ return;
409
+ const type = filterState.filterQueryInfo.type;
410
+ const recentSearch = {
411
+ filterState: type === CaseSearchQueryType.BASIC ? filterState.filterInfo : {},
412
+ sortState: filterState.sortInfo,
413
+ queryString: type === CaseSearchQueryType.BASIC
414
+ ? filterState.filterQueryInfo.queryString
415
+ : filterState.filterQueryInfo.parsedQuery,
416
+ type,
417
+ };
418
+ try {
419
+ updateUserPreferences(dispatchToGlobalMetadataReducer, loggedInUserRights.data.getSSOUsername(), [{ key: UserPreferencesKeys.mostRecentSearch, value: JSON.stringify(recentSearch) }], 'add');
420
+ }
421
+ catch (e) {
422
+ console.error('Could not save filter query in user preferences');
423
+ }
424
+ }
217
425
  // effect to update url query and call get case api whenever filter state changes
218
426
  useEffect(() => {
219
- var _a, _b, _c;
427
+ var _a, _b, _c, _d;
220
428
  if (!isFirstMount.current) {
221
429
  const urlQuery = (isNoFilterApplied(filterState) || isOnlyDefaultFilterApplied(filterState)) &&
222
430
  !((_a = filterState.filterQueryInfo) === null || _a === void 0 ? void 0 : _a.queryString) &&
223
431
  !filterState.sortInfo.column
224
432
  ? ''
225
433
  : createURLQueryFromFilterState(filterState);
434
+ const paginationKey = `p${(_b = filterState.paginationInfo) === null || _b === void 0 ? void 0 : _b.currentPage}_s${(_c = filterState.paginationInfo) === null || _c === void 0 ? void 0 : _c.pageSize}`;
435
+ const advanceSearchKey = [
436
+ ((_d = filterState.filterQueryInfo) === null || _d === void 0 ? void 0 : _d.parsedQuery) || '',
437
+ JSON.stringify(filterState.advanceSearchDateRanges || null),
438
+ ].join('|');
439
+ const fullQueryKey = `${urlQuery}_${paginationKey}_${advanceSearchKey}`;
440
+ if (fullQueryKey === lastPushedQueryRef.current) {
441
+ return;
442
+ }
443
+ if (urlQuery !== lastPushedQueryRef.current) {
444
+ clearPageCursors();
445
+ }
226
446
  setCurrentQuery(CaseListDispatch, urlQuery);
447
+ lastPushedQueryRef.current = urlQuery;
227
448
  searchParams[FILTER_URL_QUERY_SEARCH_PARAM] = encodeURIComponent(urlQuery);
228
- searchParams[FILTER_URL_CURRENT_PAGE_SEARCH_PARAM] = (_b = filterState.paginationInfo) === null || _b === void 0 ? void 0 : _b.currentPage.toString();
229
- searchParams[FILTER_URL_PAGE_SIZE_SEARCH_PARAM] = (_c = filterState.paginationInfo) === null || _c === void 0 ? void 0 : _c.pageSize.toString();
230
449
  searchParams[FILTER_URL_QUERY_TYPE] = filterState.filterQueryInfo.type;
450
+ delete searchParams[FILTER_URL_CURRENT_PAGE_SEARCH_PARAM];
451
+ delete searchParams[FILTER_URL_PAGE_SIZE_SEARCH_PARAM];
231
452
  props.routeProps.history.push({
232
453
  search: getStringifiedParams(searchParams),
233
454
  });
234
455
  saveFilterQueryInUserPreferences();
235
- // so that we don't call get cases every time user switches between basic and advanced without any filters applied
236
- if (isSearchTypeChanged &&
237
- !filterState.filterQueryInfo.queryString &&
238
- isNoFilterApplied(filterState) &&
239
- filterValuesFromFacetResponse // if this is null, it means it is the first page load so get cases anyway
240
- )
241
- return;
242
456
  getCases(filterState);
243
457
  }
244
458
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -248,17 +462,46 @@ export function CaseList(props) {
248
462
  if (bookmarkedAccounts.isFetching ||
249
463
  managedAccounts.isFetching ||
250
464
  caseGroups.isFetching ||
251
- caseGroups.data === undefined)
465
+ caseGroups.data === undefined ||
466
+ caseRecordTypes.isFetching ||
467
+ isEmpty(caseRecordTypes.data))
252
468
  return;
469
+ const decodedQueryFromUrl = (() => {
470
+ if (!queryFromUrl || queryFromUrl === 'undefined') {
471
+ return '';
472
+ }
473
+ try {
474
+ return decodeURIComponent(queryFromUrl);
475
+ }
476
+ catch (_a) {
477
+ return queryFromUrl;
478
+ }
479
+ })();
253
480
  // when user manually changes url and hit enter, new result is fetched without refreshing the page
254
481
  if (!isFirstMount.current) {
255
- if (queryFromUrl !== currentQuery) {
256
- const filterStateFromQueryUrl = createFilterStateFromUrlQuery(queryFromUrl, globalMetadataState, pageSizeFromUrl, currentPageFromUrl, searchType);
482
+ if (decodedQueryFromUrl &&
483
+ decodedQueryFromUrl !== currentQuery &&
484
+ decodedQueryFromUrl !== lastPushedQueryRef.current) {
485
+ const filterStateFromQueryUrl = createFilterStateFromUrlQuery(decodedQueryFromUrl, globalMetadataState, undefined, 1, searchType);
257
486
  updateFilterState(filterDispatch, filterStateFromQueryUrl);
258
487
  }
259
488
  return;
260
489
  }
261
490
  if (isFirstMount.current) {
491
+ if (searchParams.rhcd) {
492
+ // this is to check if rhcd is passed on first load
493
+ setRHCDValue(searchParams.rhcd);
494
+ }
495
+ const hasExplicitUrlQuery = Boolean(decodedQueryFromUrl.trim());
496
+ if (hasExplicitUrlQuery && decodedQueryFromUrl !== currentQuery) {
497
+ const { initFilterState, defaultSearchName } = useFilterStateInit.set(decodedQueryFromUrl, undefined, 1, searchType);
498
+ setDefaultSavedSearchName(defaultSearchName);
499
+ setCurrentQuery(CaseListDispatch, decodedQueryFromUrl);
500
+ lastPushedQueryRef.current = decodedQueryFromUrl;
501
+ isFirstMount.current = false;
502
+ updateFilterState(filterDispatch, initFilterState);
503
+ return;
504
+ }
262
505
  // user came to page from another tab - second time on page as currentQuery is set
263
506
  // - keep state and show the result that we already have in state
264
507
  // - update url to reflect filter state
@@ -266,8 +509,6 @@ export function CaseList(props) {
266
509
  if (currentQuery) {
267
510
  const navObj = {
268
511
  [FILTER_URL_QUERY_SEARCH_PARAM]: encodeURIComponent(currentQuery),
269
- [FILTER_URL_PAGE_SIZE_SEARCH_PARAM]: filterState.paginationInfo.pageSize,
270
- [FILTER_URL_CURRENT_PAGE_SEARCH_PARAM]: filterState.paginationInfo.currentPage,
271
512
  [FILTER_URL_QUERY_TYPE]: filterState.filterQueryInfo.type,
272
513
  };
273
514
  props.routeProps.history.replace({ search: getStringifiedParams(navObj) });
@@ -275,35 +516,31 @@ export function CaseList(props) {
275
516
  isFirstMount.current = false;
276
517
  return;
277
518
  }
278
- /*** user comes to this point on first time app load landing on case list ***/
279
- if (searchParams.rhcd) {
280
- // this is to check if rhcd is passed on first load
281
- setRHCDValue(searchParams.rhcd);
282
- }
283
519
  // set filter state based on url or default saved search
284
- const { initFilterState, defaultSearchName } = useFilterStateInit.set(decodeURIComponent(queryFromUrl), pageSizeFromUrl, currentPageFromUrl, searchType);
520
+ // Remove when we get OFFSET field from SCT
521
+ // Always reset to page 1 on fresh load — cursor-based pagination
522
+ // has no stored cursors after refresh, so page > 1 would cause a mismatch
523
+ const { initFilterState, defaultSearchName } = useFilterStateInit.set(decodedQueryFromUrl, undefined, 1, searchType);
285
524
  // to set default saved search name
286
525
  setDefaultSavedSearchName(defaultSearchName);
287
526
  // set default params when they are empty
288
- if (!queryFromUrl) {
527
+ if (!decodedQueryFromUrl) {
289
528
  searchParams[FILTER_URL_QUERY_SEARCH_PARAM] = ' orderBy lastModifiedDate desc';
290
529
  }
291
- setCurrentQuery(CaseListDispatch, queryFromUrl);
530
+ setCurrentQuery(CaseListDispatch, decodedQueryFromUrl);
292
531
  isFirstMount.current = false;
293
532
  // we only update the state without api call as we fetch result in another useEffect that observes the state
294
533
  updateFilterState(filterDispatch, initFilterState);
295
534
  }
296
535
  // eslint-disable-next-line react-hooks/exhaustive-deps
297
- }, [managedAccounts, bookmarkedAccounts, caseGroups, queryFromUrl, pageSizeFromUrl, currentPageFromUrl]);
298
- // effect to initially set the filter state to expanded and when we switch from advanced to basic mode
536
+ }, [managedAccounts, bookmarkedAccounts, caseGroups, caseRecordTypes, queryFromUrl]);
537
+ // effect to initially set the filter state to expanded on load
299
538
  useEffect(() => {
300
- // currently there is no easy way to set the panel as expanded on initial load
301
- // also we only use the standalone panel and manually change the panel state on toggle btn click
302
- isCaseListFilterPanelExanded && isXLScreen && isBasicSearchMode && toggleFilterSection(true);
539
+ isCaseListFilterPanelExanded && isXLScreen && toggleFilterSection(true);
303
540
  // eslint-disable-next-line react-hooks/exhaustive-deps
304
- }, [isBasicSearchMode]);
541
+ }, []);
305
542
  const onConfirmTraditionalSupportAgreement = () => {
306
- updateCaseListTraditionalSupportAgreed(globalDispatchContext, true);
543
+ setTraditionalSupportSessionAgreed(globalDispatchContext, true);
307
544
  };
308
545
  const displayRHCDAlert = () => {
309
546
  const openClosedCopy = `Only showing cases that were ${RHCDValue} during the selected time range specified in
@@ -327,12 +564,6 @@ export function CaseList(props) {
327
564
  return (React.createElement(React.Fragment, null,
328
565
  React.createElement(CSSUserModal, { onConfirmTraditionalSupportAgreement: onConfirmTraditionalSupportAgreement, display: !caseListTraditionalSupportAgreed }),
329
566
  React.createElement("article", { id: "rh-support-cases", className: "cases-main" },
330
- isSolrSearchDown && (React.createElement(Alert, { isInline: true, variant: AlertVariant.warning, component: "p", title: React.createElement(Trans, null,
331
- "Case search is working with limited functionality. Please check",
332
- ' ',
333
- React.createElement("a", { href: "https://status.redhat.com", target: "_blank", rel: "noreferrer", "data-tracking-id": "caselist-redirect-status-page" }, "status page"),
334
- ' ',
335
- "for details.") })),
336
567
  React.createElement("section", { className: "case-search-top" },
337
568
  !isEmpty(RHCDValue) && isRHCDAlertShown && React.createElement("div", { className: "push-bottom" }, displayRHCDAlert()),
338
569
  React.createElement("div", { className: "search-wrapper" },
@@ -340,17 +571,17 @@ export function CaseList(props) {
340
571
  React.createElement(NewCaseButton, { routeProps: props.routeProps })),
341
572
  React.createElement(ErrorBoundary, { errorMsgInfo: { message: t('There was an error loading case search input') } },
342
573
  React.createElement(CaseSearch, { defaultSavedSearchName: defaultSavedSearchName }))),
343
- isBasicSearchMode && (React.createElement(ErrorBoundary, { errorMsgInfo: { message: t('There was an error loading filter chips') } },
344
- React.createElement(CaseListFilterChips, { productVersionPivotValues: get(pivotValues, SolrPivotKeys.product_version, []), isSolrSearchDown: isSolrSearchDown })))),
574
+ React.createElement(ErrorBoundary, { errorMsgInfo: { message: t('There was an error loading filter chips') } },
575
+ React.createElement(CaseListFilterChips, null))),
345
576
  React.createElement("section", { className: "case-search-bottom" },
346
- isBasicSearchMode && (React.createElement("aside", { className: `case-search-filters ${((_a = filterSectionRef.current) === null || _a === void 0 ? void 0 : _a.expanded) ? '' : 'collapsed'}` },
347
- React.createElement("h2", { className: "filter-header pf-v6-u-display-flex" }, ((_b = filterSectionRef.current) === null || _b === void 0 ? void 0 : _b.expanded) ? (React.createElement(React.Fragment, null,
577
+ React.createElement("aside", { className: `case-search-filters ${((_g = filterSectionRef.current) === null || _g === void 0 ? void 0 : _g.expanded) ? '' : 'collapsed'}` },
578
+ React.createElement("h2", { className: "filter-header pf-v6-u-display-flex" }, ((_h = filterSectionRef.current) === null || _h === void 0 ? void 0 : _h.expanded) ? (React.createElement(React.Fragment, null,
348
579
  React.createElement(Button, { isInline: true, className: "pf-v6-u-flex-shrink-0 pf-v6-u-flex-none case-search-filter-text-button", variant: "link", title: t('Collapse filter section'), "data-tracking-id": "collapse-case-list-filter", onClick: onToggleFilterBtnClick, iconPosition: "right", icon: React.createElement(OpenDrawerRightIcon, { className: "mirrored" }) },
349
580
  React.createElement(Trans, null, "Filters")))) : (React.createElement(Button, { isInline: true, className: "pf-v6-c-button pf-m-link pf-m-inline pf-v6-u-flex-shrink-0 pf-v6-u-flex-none pf-v6-u-display-flex pf-v6-u-align-items-center pf-v6-u-justify-content-center pf-v6-u-px-lg", variant: "link", title: t('Expand filter section'), "data-tracking-id": "expand-case-list-filter", onClick: onToggleFilterBtnClick, iconPosition: "right", icon: React.createElement(OpenDrawerRightIcon, null) }, isXLScreen ? null : React.createElement(Trans, null, "Filters")))),
350
581
  React.createElement("div", { className: "filter-wrapper" },
351
582
  React.createElement("pfe-collapse-panel", { id: "case-filters-panel", "pfe-animation": "false", ref: filterSectionRef },
352
583
  React.createElement(ErrorBoundary, { errorMsgInfo: { message: t('There was an error loading filters') } },
353
- React.createElement(CaseListFilters, { filterValues: filterValuesFromFacetResponse, allCaseTypes: allCaseTypes, allCaseStatuses: allCaseStatuses, allCaseSeverities: allCaseSeverities, allProducts: allProducts, isSolrSearchDown: isSolrSearchDown })))))),
584
+ React.createElement(CaseListFilters, { allCaseTypes: allCaseTypes, allCaseStatuses: allCaseStatuses, allCaseSeverities: allCaseSeverities, allProducts: allProducts }))))),
354
585
  React.createElement("section", { className: "case-search-table pf-v6-u-display-flex pf-v6-u-flex-direction-column" },
355
- React.createElement(CaseListTable, { caseList: caseList, caseGroups: caseGroups.data || [], loggedInUserRights: loggedInUserRights.data, sortInfo: filterState.sortInfo, paginationInfo: filterState.paginationInfo, isCaseListPageLoading: isFetching, hasError: hasError, isSolrDown: isSolrSearchDown }))))));
586
+ React.createElement(CaseListTable, { caseList: caseList, caseGroups: caseGroups.data || [], loggedInUserRights: loggedInUserRights.data, sortInfo: filterState.sortInfo, isCaseListPageLoading: isFetching, hasError: hasError, hasNextPage: hasNextPage, isLoadingMore: isLoadingMore, loadMoreError: loadMoreError, loadMoreRetryCount: loadMoreRetryCount, onRetryLoadMore: retryLoadMore, onCasesCloseSuccess: () => getCases(filterState), sentinelRef: sentinelRef }))))));
356
587
  }