@rh-support/troubleshoot 0.2.115 → 0.2.118

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 (52) hide show
  1. package/lib/esm/components/CaseEditView/ActiveCustomerEscalation/ActiveCustomerEscalation.d.ts.map +1 -1
  2. package/lib/esm/components/CaseEditView/ActiveCustomerEscalation/ActiveCustomerEscalation.js +6 -4
  3. package/lib/esm/components/CaseEditView/ActiveCustomerEscalation/RequestEscalationModal.d.ts.map +1 -1
  4. package/lib/esm/components/CaseEditView/ActiveCustomerEscalation/RequestEscalationModal.js +114 -52
  5. package/lib/esm/components/CaseEditView/ConfirmationModals/ReopenCaseModal.js +1 -1
  6. package/lib/esm/components/CaseEditView/Tabs/CaseDetails/CaseOpenshiftClusterId/CaseOpenshiftClusterId.d.ts.map +1 -1
  7. package/lib/esm/components/CaseEditView/Tabs/CaseDetails/CaseOpenshiftClusterId/CaseOpenshiftClusterId.js +27 -44
  8. package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/CaseDiscussion.d.ts.map +1 -1
  9. package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/PostComment.d.ts.map +1 -1
  10. package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/PostComment.js +14 -2
  11. package/lib/esm/components/CaseEditView/Tabs/RMEEscalations/RMEEscalationList.d.ts.map +1 -1
  12. package/lib/esm/components/CaseEditView/Tabs/RMEEscalations/RMEEscalationList.js +10 -11
  13. package/lib/esm/components/CaseManagement/OpenShiftClusterId.d.ts.map +1 -1
  14. package/lib/esm/components/CaseManagement/OpenShiftClusterId.js +38 -52
  15. package/lib/esm/components/CaseManagement/OpenshiftDropdownV4.d.ts +2 -2
  16. package/lib/esm/components/CaseManagement/OpenshiftDropdownV4.d.ts.map +1 -1
  17. package/lib/esm/components/CaseManagement/OpenshiftDropdownV4.js +122 -84
  18. package/lib/esm/components/Recommendations/AlertToastWrapper.d.ts +1 -0
  19. package/lib/esm/components/Recommendations/AlertToastWrapper.d.ts.map +1 -1
  20. package/lib/esm/components/Recommendations/AlertToastWrapper.js +4 -2
  21. package/lib/esm/components/SessionRestore/RestoreLastSessionModal.d.ts +9 -0
  22. package/lib/esm/components/SessionRestore/RestoreLastSessionModal.d.ts.map +1 -0
  23. package/lib/esm/components/SessionRestore/RestoreLastSessionModal.js +43 -0
  24. package/lib/esm/components/SessionRestore/SessionRestore.d.ts.map +1 -1
  25. package/lib/esm/components/SessionRestore/SessionRestore.js +11 -5
  26. package/lib/esm/components/SubmitCase/ResubmitToast.d.ts +7 -0
  27. package/lib/esm/components/SubmitCase/ResubmitToast.d.ts.map +1 -0
  28. package/lib/esm/components/SubmitCase/ResubmitToast.js +25 -0
  29. package/lib/esm/components/wizardLayout/GlobalTroubleshootEffects.d.ts.map +1 -1
  30. package/lib/esm/components/wizardLayout/GlobalTroubleshootEffects.js +4 -1
  31. package/lib/esm/components/wizardLayout/WizardAside.d.ts +1 -0
  32. package/lib/esm/components/wizardLayout/WizardAside.d.ts.map +1 -1
  33. package/lib/esm/components/wizardLayout/WizardAside.js +1 -1
  34. package/lib/esm/components/wizardLayout/WizardLayout.d.ts.map +1 -1
  35. package/lib/esm/components/wizardLayout/WizardLayout.js +6 -5
  36. package/lib/esm/reducers/CaseConstNTypes.d.ts +4 -1
  37. package/lib/esm/reducers/CaseConstNTypes.d.ts.map +1 -1
  38. package/lib/esm/reducers/CaseConstNTypes.js +4 -0
  39. package/lib/esm/reducers/CaseReducer.d.ts +12 -0
  40. package/lib/esm/reducers/CaseReducer.d.ts.map +1 -1
  41. package/lib/esm/reducers/CaseReducer.js +35 -1
  42. package/lib/esm/reducers/ClusterRecommendationsReducer.d.ts +5 -2
  43. package/lib/esm/reducers/ClusterRecommendationsReducer.d.ts.map +1 -1
  44. package/lib/esm/reducers/ClusterRecommendationsReducer.js +19 -6
  45. package/lib/esm/reducers/SessionRestoreReducer.d.ts +5 -2
  46. package/lib/esm/reducers/SessionRestoreReducer.d.ts.map +1 -1
  47. package/lib/esm/reducers/SessionRestoreReducer.js +24 -1
  48. package/lib/esm/scss/_pf4-overrides.scss +1 -1
  49. package/lib/esm/utils/caseOpenshiftClusterIdUtils.d.ts +4 -2
  50. package/lib/esm/utils/caseOpenshiftClusterIdUtils.d.ts.map +1 -1
  51. package/lib/esm/utils/caseOpenshiftClusterIdUtils.js +1 -9
  52. package/package.json +9 -9
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  };
10
10
  import ExclamationCircleIcon from '@patternfly/react-icons/dist/js/icons/exclamation-circle-icon';
11
11
  import { GlobalMetadataStateContext } from '@rh-support/react-context';
12
- import { getConfigField, getUrlParsedParams, getVersion, PCM_CONFIG_FIELD_TYPE } from '@rh-support/utils';
12
+ import { getUrlParsedParams, getVersion } from '@rh-support/utils';
13
13
  import isEmpty from 'lodash/isEmpty';
14
14
  import isEqual from 'lodash/isEqual';
15
15
  import React, { useContext, useEffect, useState } from 'react';
@@ -21,9 +21,9 @@ import { RouteContext } from '../../context/RouteContext';
21
21
  import { getUpdatedDescription } from '../../reducers/CaseHelpers';
22
22
  import { setCaseDetails, setCaseState } from '../../reducers/CaseReducer';
23
23
  import { fetchClusterRecommendations } from '../../reducers/ClusterRecommendationsReducer';
24
- import { getIsClusterIdInvalid, isClusterIdEnabledForProduct } from '../../utils/caseOpenshiftClusterIdUtils';
24
+ import { getIsClusterIdInvalid, isClusterIdEnabledForProduct, } from '../../utils/caseOpenshiftClusterIdUtils';
25
25
  import { NoClusterIDReasonSelector } from './NoClusterIDReasonSelector';
26
- import { fetchClusterIdDetails, OpenshiftDropdownV4 } from './OpenshiftDropdownV4';
26
+ import { OpenshiftDropdownV4 } from './OpenshiftDropdownV4';
27
27
  import { OpenShiftV3Inputbox } from './OpenShiftV3Inputbox';
28
28
  export const v3Tov4TransitionLink = () => (React.createElement("a", { className: "show-target", href: "https://access.redhat.com/documentation/en-us/openshift_container_platform/4.8/html-single/migrating_from_openshift_container_platform_3_to_4/index", target: "_blank", rel: "noopener noreferrer" },
29
29
  React.createElement(Trans, null, "How to transition from v3 to v4?")));
@@ -40,7 +40,7 @@ export const isInvalidErrorMessage = () => (React.createElement(React.Fragment,
40
40
  discoverV4ClusterIdLink()));
41
41
  export function OpenShiftClusterId() {
42
42
  const queryParams = getUrlParsedParams(useLocation().search);
43
- const { openshiftClusterID, product, version, issue, environment, periodicityOfIssue, timeFramesAndUrgency, openshiftClusterVersion, noClusterIdReason, noClusterIdReasonExplanation, v3ClusterName, selectedAccountDetails, } = useCaseSelector((state) => ({
43
+ const { openshiftClusterID, product, version, issue, environment, periodicityOfIssue, timeFramesAndUrgency, noClusterIdReason, noClusterIdReasonExplanation, v3ClusterName, openshiftDisplayName, selectedAccountDetails, } = useCaseSelector((state) => ({
44
44
  openshiftClusterID: state.caseDetails.openshiftClusterID,
45
45
  product: state.caseDetails.product,
46
46
  version: state.caseDetails.version,
@@ -48,17 +48,17 @@ export function OpenShiftClusterId() {
48
48
  environment: state.caseDetails.environment,
49
49
  periodicityOfIssue: state.caseDetails.periodicityOfIssue,
50
50
  timeFramesAndUrgency: state.caseDetails.timeFramesAndUrgency,
51
- openshiftClusterVersion: state.caseDetails.openshiftClusterVersion,
52
51
  noClusterIdReason: state.caseDetails.noClusterIdReason,
53
52
  noClusterIdReasonExplanation: state.caseDetails.noClusterIdReasonExplanation,
54
53
  v3ClusterName: state.v3ClusterName,
54
+ openshiftDisplayName: state.openshiftDisplayName,
55
55
  selectedAccountDetails: state.selectedAccountDetails,
56
56
  }), isEqual);
57
57
  const caseDispatch = useCaseDispatch();
58
- const { globalMetadataState: { pcmConfig, allProducts, loggedInUserRights }, } = useContext(GlobalMetadataStateContext);
58
+ const { globalMetadataState: { allProducts, loggedInUserRights }, } = useContext(GlobalMetadataStateContext);
59
59
  const { routeState: { showValidationErrorAlert }, } = useContext(RouteContext);
60
60
  const clusterRecommendationsDispatch = useContext(ClusterRecommendationsDispatchContext);
61
- const { clusterRecommendationsState: { clusterRecommendations }, } = useContext(ClusterRecommendationsContext);
61
+ const { clusterRecommendationsState: { clusterRecommendationsCache }, } = useContext(ClusterRecommendationsContext);
62
62
  const majorVersion = (version && getVersion(version).major) || '';
63
63
  const isOpenShiftV3 = majorVersion === '3';
64
64
  const isCustomer = loggedInUserRights.data.isAccountSameAsLoggedInAccount(selectedAccountDetails.data.accountNumber);
@@ -67,11 +67,11 @@ export function OpenShiftClusterId() {
67
67
  const [v3Selected, setV3Selected] = useState(false);
68
68
  const [dontKnowSelected, setDontKnowSelected] = useState(false);
69
69
  const [selectedReason, setSelectedReason] = useState('');
70
- const isClusterRecommendationEnabled = getConfigField(pcmConfig.data, 'isClusterRecommendationEnabled', PCM_CONFIG_FIELD_TYPE.FEATURE_FLAG);
71
70
  const resetClusterData = () => {
72
71
  clusterStateReset();
73
72
  setCaseDetails(caseDispatch, {
74
73
  openshiftClusterID: '',
74
+ openshiftClusterVersion: '',
75
75
  noClusterIdReasonExplanation: '',
76
76
  noClusterIdReason: '',
77
77
  });
@@ -82,41 +82,26 @@ export function OpenShiftClusterId() {
82
82
  setDontKnowSelected(false);
83
83
  setV3Selected(false);
84
84
  };
85
- const setCusterId = (openshiftClusterID, clusterDetails) => __awaiter(this, void 0, void 0, function* () {
86
- setCaseDetails(caseDispatch, {
87
- openshiftClusterID,
88
- openshiftClusterVersion: '',
89
- noClusterIdReason: '',
90
- noClusterIdReasonExplanation: '',
91
- });
92
- setCaseState(caseDispatch, { v3ClusterName: '' });
93
- setClusterVersion(openshiftClusterID, clusterDetails);
94
- });
95
- const setClusterVersion = (openshiftClusterID, clusterDetails) => __awaiter(this, void 0, void 0, function* () {
96
- if (!openshiftClusterID || getIsClusterIdInvalid(openshiftClusterID))
97
- return;
98
- let openshiftClusterVersion;
99
- if (clusterDetails &&
100
- clusterDetails.external_cluster_id === openshiftClusterID &&
101
- clusterDetails.openshift_version) {
102
- openshiftClusterVersion = clusterDetails.openshift_version;
103
- }
104
- else {
105
- const clusterDetails = yield fetchClusterIdDetails(openshiftClusterID);
106
- openshiftClusterVersion = clusterDetails === null || clusterDetails === void 0 ? void 0 : clusterDetails.openshift_version;
107
- }
108
- setCaseDetails(caseDispatch, { openshiftClusterVersion });
109
- });
85
+ /**
86
+ * Hook to show cluster fields and check if cluster id comes from url
87
+ */
110
88
  useEffect(() => {
111
89
  var _a;
112
90
  const isClusterVisible = () => __awaiter(this, void 0, void 0, function* () {
113
91
  var _b;
114
92
  const hasCluster = yield isClusterIdEnabledForProduct(product, (_b = allProducts.data) === null || _b === void 0 ? void 0 : _b.productsResult);
115
93
  setShowClusterId(hasCluster);
116
- // we get cluster id from url and validate it
94
+ // if clusterId is already populated it means it comes from session and
95
+ // we ignore url clusterId otherwise we get cluster id from url and validate it
117
96
  const clusterIdFromUrl = queryParams === null || queryParams === void 0 ? void 0 : queryParams.clusterId;
118
- if (hasCluster && clusterIdFromUrl && clusterIdFromUrl !== openshiftClusterID) {
119
- setCusterId(clusterIdFromUrl);
97
+ if (hasCluster &&
98
+ clusterIdFromUrl &&
99
+ isEmpty(openshiftClusterID) &&
100
+ isEmpty(noClusterIdReason) &&
101
+ isEmpty(noClusterIdReasonExplanation)) {
102
+ setCaseDetails(caseDispatch, {
103
+ openshiftClusterID: clusterIdFromUrl,
104
+ });
120
105
  const isClusterIdInvalid = getIsClusterIdInvalid(clusterIdFromUrl);
121
106
  if (isClusterIdInvalid) {
122
107
  // if we get invalid id from url we need to add red line to dropdown
@@ -131,22 +116,18 @@ export function OpenShiftClusterId() {
131
116
  isClusterVisible();
132
117
  }
133
118
  // eslint-disable-next-line react-hooks/exhaustive-deps
134
- }, [product, version, pcmConfig, allProducts.data]);
119
+ }, [product, version, allProducts.data]);
135
120
  // On preview page user may change product and version we need to reset internal state
136
121
  // context api state will be reset on parent component each time user changes product and version
137
122
  useEffect(() => {
138
123
  clusterStateReset();
139
124
  }, [product, version]);
140
125
  /**
141
- * Hook to make sure that if cluster id comes from session or someother source
142
- * we also fetch the details for the cluster id so that we can have fields like cluster version while creating the case
143
- */
126
+ * Hook to set clusterId fields when comes from session or backward/forward
127
+ **/
144
128
  useEffect(() => {
145
129
  const isClusterIdInvalid = getIsClusterIdInvalid(openshiftClusterID);
146
130
  setIsClusterIdInValid(isClusterIdInvalid);
147
- if (openshiftClusterID && !isClusterIdInvalid && isEmpty(openshiftClusterVersion)) {
148
- setClusterVersion(openshiftClusterID);
149
- }
150
131
  // when user click on back and continue button, need to show v3 text box or reasons dropdown
151
132
  if (!isEmpty(v3ClusterName) ||
152
133
  (noClusterIdReason === 'Other' && noClusterIdReasonExplanation === 'v3-cluster')) {
@@ -157,11 +138,9 @@ export function OpenShiftClusterId() {
157
138
  setDontKnowSelected(true);
158
139
  setSelectedReason('dont-have-id');
159
140
  }
160
- const canFetchClusterRecommendation = isClusterRecommendationEnabled && !isClusterIdInvalid && !isEmpty(openshiftClusterID);
161
- // To prevent refetching clusterRecommendations checking for clusterRecommendations data length
141
+ const canFetchClusterRecommendation = !isClusterIdInvalid && !isEmpty(openshiftClusterID);
162
142
  canFetchClusterRecommendation &&
163
- !clusterRecommendations.data.length &&
164
- fetchClusterRecommendations(clusterRecommendationsDispatch, openshiftClusterID);
143
+ fetchClusterRecommendations(clusterRecommendationsDispatch, openshiftClusterID, clusterRecommendationsCache);
165
144
  // eslint-disable-next-line react-hooks/exhaustive-deps
166
145
  }, [noClusterIdReason]);
167
146
  const onClusterIdStateUpdate = (selectedCluster) => {
@@ -178,7 +157,7 @@ export function OpenShiftClusterId() {
178
157
  setV3Selected(true);
179
158
  setSelectedReason(selectedId);
180
159
  setCaseDetails(caseDispatch, {
181
- openshiftClusterID,
160
+ openshiftClusterID: '',
182
161
  openshiftClusterVersion: '',
183
162
  noClusterIdReason: 'Other',
184
163
  noClusterIdReasonExplanation: 'v3-cluster',
@@ -186,10 +165,17 @@ export function OpenShiftClusterId() {
186
165
  return;
187
166
  }
188
167
  const isClusterInvalid = getIsClusterIdInvalid(selectedId);
189
- const canFetchClusterRecommendation = !isClusterInvalid && isClusterRecommendationEnabled;
190
168
  setIsClusterIdInValid(isClusterInvalid);
191
- setCusterId(selectedId, selectedCluster);
192
- canFetchClusterRecommendation && fetchClusterRecommendations(clusterRecommendationsDispatch, selectedId);
169
+ setCaseDetails(caseDispatch, {
170
+ openshiftClusterID: selectedId,
171
+ openshiftClusterVersion: selectedCluster.openshift_version,
172
+ noClusterIdReason: '',
173
+ noClusterIdReasonExplanation: '',
174
+ });
175
+ setCaseState(caseDispatch, { v3ClusterName: '', openshiftDisplayName: selectedCluster.display_name });
176
+ !isClusterInvalid &&
177
+ !isEmpty(selectedId) &&
178
+ fetchClusterRecommendations(clusterRecommendationsDispatch, selectedId, clusterRecommendationsCache);
193
179
  };
194
180
  const clusterIdDropdownFormInstructions = () => {
195
181
  const errorMessage = isClusterIdInvalid
@@ -219,7 +205,7 @@ export function OpenShiftClusterId() {
219
205
  if (!showClusterId)
220
206
  return null;
221
207
  return (React.createElement(React.Fragment, null,
222
- !isOpenShiftV3 && (React.createElement(OpenshiftDropdownV4, { openshiftClusterIDState: openshiftClusterID || selectedReason, onClusterIdStateUpdate: onClusterIdStateUpdate, isClusterIdInvalid: showValidationErrorAlert &&
208
+ !isOpenShiftV3 && (React.createElement(OpenshiftDropdownV4, { openshiftDisplayName: openshiftDisplayName, openshiftClusterIDState: openshiftClusterID || selectedReason, onClusterIdStateUpdate: onClusterIdStateUpdate, isClusterIdInvalid: showValidationErrorAlert &&
223
209
  ((isEmpty(openshiftClusterID) && isEmpty(selectedReason)) || isClusterIdInvalid), clusterIdDropdownFormInstructions: clusterIdDropdownFormInstructions(), onClusterClear: resetClusterData, isV4: majorVersion === '4' })),
224
210
  noClusterIdReasonExplanation !== 'v3-cluster' && dontKnowSelected && !isOpenShiftV3 && (React.createElement(NoClusterIDReasonSelector, { noClusterIdReasonExplanation: noClusterIdReasonExplanation, noClusterIdReason: noClusterIdReason, onReasonInputBoxChanged: onReasonExplanationInputBoxChanged, onReasonChange: onReasonChange, isInValid: isInVaidNoClusterIdReason, isCustomer: isCustomer })),
225
211
  (v3Selected || isOpenShiftV3) && (React.createElement(OpenShiftV3Inputbox, { v3ClusterName: v3ClusterName, onReasonInputBoxChanged: v3ClusterNameInputBoxChanged, isInValid: isEmpty(v3ClusterName.trim()) && showValidationErrorAlert, v3Selected: v3Selected }))));
@@ -9,11 +9,11 @@ interface IProps extends IDClassNameProps {
9
9
  isV4: boolean;
10
10
  isDisabled?: boolean;
11
11
  noClusterIdReasonExplanation?: string;
12
+ openshiftDisplayName?: string;
12
13
  }
13
- declare const fetchClusterIdDetails: (clusterId: string) => Promise<import("@cee-eng/hydrajs/@types/models/cloud").ICluster>;
14
14
  declare function OpenshiftDropdownV4(props: IProps): JSX.Element;
15
15
  declare namespace OpenshiftDropdownV4 {
16
16
  var defaultProps: {};
17
17
  }
18
- export { OpenshiftDropdownV4, fetchClusterIdDetails };
18
+ export { OpenshiftDropdownV4 };
19
19
  //# sourceMappingURL=OpenshiftDropdownV4.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"OpenshiftDropdownV4.d.ts","sourceRoot":"","sources":["../../../../src/components/CaseManagement/OpenshiftDropdownV4.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAgC,MAAM,sCAAsC,CAAC;AAE1G,OAAO,EAAE,gBAAgB,EAAuB,MAAM,0BAA0B,CAAC;AAWjF,UAAU,MAAO,SAAQ,gBAAgB;IACrC,uBAAuB,EAAE,MAAM,CAAC;IAChC,sBAAsB,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,oBAAoB,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACzF,kBAAkB,EAAE,OAAO,CAAC;IAC5B,iCAAiC,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC;IAChD,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,IAAI,EAAE,OAAO,CAAC;IACd,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,4BAA4B,CAAC,EAAE,MAAM,CAAC;CACzC;AAQD,QAAA,MAAM,qBAAqB,cAAqB,MAAM,qEASrD,CAAC;AAeF,iBAAS,mBAAmB,CAAC,KAAK,EAAE,MAAM,eAwTzC;kBAxTQ,mBAAmB;;;AA2T5B,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,CAAC"}
1
+ {"version":3,"file":"OpenshiftDropdownV4.d.ts","sourceRoot":"","sources":["../../../../src/components/CaseManagement/OpenshiftDropdownV4.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAC;AAG5E,OAAO,EAAE,gBAAgB,EAAuB,MAAM,0BAA0B,CAAC;AAcjF,UAAU,MAAO,SAAQ,gBAAgB;IACrC,uBAAuB,EAAE,MAAM,CAAC;IAChC,sBAAsB,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,oBAAoB,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACzF,kBAAkB,EAAE,OAAO,CAAC;IAC5B,iCAAiC,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC;IAChD,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,IAAI,EAAE,OAAO,CAAC;IACd,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,4BAA4B,CAAC,EAAE,MAAM,CAAC;IACtC,oBAAoB,CAAC,EAAE,MAAM,CAAC;CACjC;AAuBD,iBAAS,mBAAmB,CAAC,KAAK,EAAE,MAAM,eAiXzC;kBAjXQ,mBAAmB;;;AAoX5B,OAAO,EAAE,mBAAmB,EAAE,CAAC"}
@@ -9,34 +9,25 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  };
10
10
  import { cloud } from '@cee-eng/hydrajs';
11
11
  import { Checkbox, Divider, Select, SelectOption, SelectVariant } from '@patternfly/react-core';
12
- import find from 'lodash/find';
13
- import findIndex from 'lodash/findIndex';
12
+ import { useLRUCache } from '@rh-support/components';
13
+ import debounce from 'lodash/debounce';
14
14
  import groupBy from 'lodash/groupBy';
15
15
  import isEmpty from 'lodash/isEmpty';
16
- import React, { useEffect, useRef, useState } from 'react';
16
+ import React, { useEffect, useMemo, useRef, useState } from 'react';
17
17
  import { Trans, useTranslation } from 'react-i18next';
18
- import { getDisplayNameForCluster } from '../../utils/caseOpenshiftClusterIdUtils';
18
+ import { getDisplayNameForCluster, getIsClusterIdInvalid, } from '../../utils/caseOpenshiftClusterIdUtils';
19
19
  import CaseOpenShiftPopover from '../CaseEditView/Tabs/CaseDetails/CaseOpenshiftClusterId/CaseOpenShiftPopover';
20
20
  const defaultProps = {
21
21
  className: '',
22
22
  id: '',
23
23
  isDisabled: false,
24
+ openshiftDisplayName: '',
24
25
  };
25
- const fetchClusterIdDetails = (clusterId) => __awaiter(void 0, void 0, void 0, function* () {
26
- try {
27
- const clustersResponse = yield cloud.getAccountClusters({
28
- order: 'display_name asc',
29
- search: `external_id ILIKE '%${clusterId}%'`,
30
- });
31
- const clusterDetails = (clustersResponse.items || []).find((item) => item.external_id === clusterId);
32
- return clusterDetails;
33
- }
34
- catch (e) { }
35
- });
36
- const createState = (external_cluster_id, display_name) => {
26
+ const createState = (external_cluster_id, display_name, openshift_version) => {
37
27
  return {
38
28
  display_name,
39
29
  external_cluster_id,
30
+ openshift_version: openshift_version || '',
40
31
  toString: () => display_name || '',
41
32
  compareTo: function (value) {
42
33
  const displayName = this.toString().toLowerCase();
@@ -47,9 +38,9 @@ const createState = (external_cluster_id, display_name) => {
47
38
  };
48
39
  function OpenshiftDropdownV4(props) {
49
40
  const { t } = useTranslation();
50
- const PER_PAGE = 20;
41
+ const PER_PAGE = 200;
51
42
  const [clustersRawResponse, setClustersRawResponse] = useState([]);
52
- const abortControllerRef = useRef(undefined);
43
+ const abortControllerRef = useRef();
53
44
  const [clustersSelectOptions, setClustersSelectOptions] = useState([]);
54
45
  const [isOpen, setIsOpen] = useState(false);
55
46
  const [validated, setValidated] = useState('default');
@@ -57,8 +48,9 @@ function OpenshiftDropdownV4(props) {
57
48
  const [showArchivedClusters, setShowArchivedClusters] = useState(false);
58
49
  const [isFetchingClusters, setIsFetchingClusters] = useState(false);
59
50
  const [totalResultsNo, setTotalResultsNo] = useState(0);
51
+ const { getFromCache, setInCache } = useLRUCache(25);
60
52
  // gets a cluster id and returns display name
61
- const getDisplayNameById = (clusters, id, noClusterIdReasonExplanation) => {
53
+ const getDisplayName = (id, noClusterIdReasonExplanation, display_name) => {
62
54
  if (isEmpty(id))
63
55
  return '';
64
56
  if (id === 'dont-have-id') {
@@ -68,8 +60,7 @@ function OpenshiftDropdownV4(props) {
68
60
  }
69
61
  if (id === 'v3-cluster')
70
62
  return t('The case is for a v3 cluster');
71
- const cluster = find(clusters, (o) => o.external_cluster_id === id);
72
- return isEmpty(cluster) ? id : getDisplayNameForCluster(cluster);
63
+ return display_name || id;
73
64
  };
74
65
  const onDropdownClear = () => __awaiter(this, void 0, void 0, function* () {
75
66
  setIsOpen(false);
@@ -103,91 +94,109 @@ function OpenshiftDropdownV4(props) {
103
94
  setIsOpen(false);
104
95
  }
105
96
  });
97
+ const dropdownHeaderOptions = useMemo(() => [
98
+ React.createElement(SelectOption, { key: 'show-hide-archived-clusters', inputId: "check-box" },
99
+ React.createElement(Checkbox, { label: t('Show archived clusters'), key: "show-archived-clusters", "aria-label": t('Show archived clusters'), id: "show-archived-clusters", "data-tracking-id": "show-hide-archived-clusters", isChecked: showArchivedClusters, className: "archived-clusters-checkbox" })),
100
+ React.createElement(Divider, { component: "div", key: 'cluster-id-options-divider-e' }),
101
+ React.createElement(SelectOption, { key: 'dont-have-id', value: createState('dont-have-id', t("I don't have my Cluster ID")) }),
102
+ ...(!props.isV4
103
+ ? [
104
+ React.createElement(SelectOption, { key: 'v3-cluster', value: createState('v3-cluster', t('The case is for a v3 cluster')) }),
105
+ ]
106
+ : []),
107
+ ],
108
+ // eslint-disable-next-line react-hooks/exhaustive-deps
109
+ [showArchivedClusters]);
106
110
  const getClusterOptions = (clusters) => {
107
- const clustersResponseGrouped = groupBy(clusters, 'dns.base_domain') || [];
111
+ const clustersResponseGrouped = groupBy(clusters, 'console_url') || [];
108
112
  const domainNames = Object.keys(clustersResponseGrouped) || [];
109
- // move undefined to the end of domains array
110
- const undefinedIndex = domainNames.findIndex((i) => i === 'undefined');
113
+ // move clusters with empty console_urls to the end of domains array
114
+ const undefinedIndex = domainNames.findIndex((i) => i === '');
111
115
  if (undefinedIndex !== -1 && undefinedIndex !== domainNames.length - 1) {
112
116
  domainNames.splice(undefinedIndex, 1);
113
- domainNames.push('undefined');
117
+ domainNames.push('');
114
118
  }
115
119
  // SelectGroup had a bug when keyboard was used to navigate
116
120
  // to show group names used disabled SelectOption, need to be replaced after bug fix
117
121
  const clusterOptions = [];
118
122
  domainNames.forEach((domain, index) => {
119
- domain !== 'undefined' &&
123
+ domain !== '' &&
120
124
  clusterOptions.push(React.createElement(SelectOption, { isDisabled: true, className: "pf-u-font-weight-bold pf-u-color-400", value: createState(domain, domain), key: domain + index }));
121
125
  clustersResponseGrouped[domain] &&
122
126
  clustersResponseGrouped[domain].forEach((cluster, i) => {
123
- clusterOptions.push(React.createElement(SelectOption, { key: cluster.external_cluster_id, value: createState(cluster.external_cluster_id, cluster.display_name) }));
127
+ clusterOptions.push(React.createElement(SelectOption, { key: cluster.external_cluster_id, value: createState(cluster.external_cluster_id, getDisplayNameForCluster(cluster) || cluster.external_cluster_id, cluster.openshift_version) }));
124
128
  });
125
129
  clusterOptions.push(React.createElement(Divider, { component: "div", key: index + domain }));
126
130
  });
127
131
  return [
128
- React.createElement(SelectOption, { key: 'show-hide-archived-clusters', inputId: "check-box" },
129
- React.createElement(Checkbox, { label: t('Show archived clusters'), key: "show-archived-clusters", "aria-label": t('Show archived clusters'), id: "show-archived-clusters", "data-tracking-id": "show-hide-archived-clusters", isChecked: showArchivedClusters, className: "archived-clusters-checkbox" })),
130
- React.createElement(Divider, { component: "div", key: 'cluster-id-options-divider-e' }),
131
- React.createElement(SelectOption, { key: 'dont-have-id', value: createState('dont-have-id', t("I don't have my Cluster ID")) }),
132
- ...(!props.isV4
133
- ? [
134
- React.createElement(SelectOption, { key: 'v3-cluster', value: createState('v3-cluster', t('The case is for a v3 cluster')) }),
135
- ]
136
- : []),
132
+ ...dropdownHeaderOptions,
137
133
  ...(clusterOptions.length !== 0 ? [React.createElement(Divider, { component: "div", key: 'cluster-id-options-divider' })] : []),
138
134
  ...clusterOptions,
139
135
  ];
140
136
  };
141
- const fetchAccountClusters = (search = '', page = 0) => __awaiter(this, void 0, void 0, function* () {
137
+ const fetchAClusterIdDetails = (clusterId) => __awaiter(this, void 0, void 0, function* () {
138
+ var _a;
142
139
  setIsFetchingClusters(true);
143
140
  try {
144
- if (abortControllerRef.current !== undefined) {
145
- // Cancel the previous request
146
- abortControllerRef.current.abort();
147
- }
148
- // recreate a new AbortController for each call
149
- let controller = new AbortController();
150
- abortControllerRef.current = controller;
151
- // query language: https://github.com/yaacov/tree-search-language
152
141
  const clustersResponse = yield cloud.getAccountClustersSubscription({
153
- order: 'display_name asc',
154
- page,
155
- size: PER_PAGE,
156
- search: `${showArchivedClusters ? '' : "status!='Archived'"} ${search && !showArchivedClusters ? 'AND' : ''} ${search ? `(external_cluster_id ILIKE '%${search}%' OR display_name ILIKE '%${search}%')` : ''}`,
142
+ search: `external_cluster_id='${clusterId}'`,
157
143
  fields: 'external_cluster_id,display_name,status,metrics.openshift_version',
158
- }, controller.signal);
144
+ });
145
+ setIsFetchingClusters(false);
146
+ return (((_a = clustersResponse.items.map((item) => {
147
+ var _a, _b;
148
+ return ({
149
+ display_name: item.display_name,
150
+ external_cluster_id: item.external_cluster_id,
151
+ openshift_version: ((_b = (_a = item === null || item === void 0 ? void 0 : item.metrics) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.openshift_version) || '',
152
+ });
153
+ })) === null || _a === void 0 ? void 0 : _a[0]) || {});
154
+ }
155
+ catch (e) {
156
+ return {};
157
+ }
158
+ });
159
+ const fetchAccountClusters = (search = '', page = 0) => __awaiter(this, void 0, void 0, function* () {
160
+ setIsFetchingClusters(true);
161
+ try {
162
+ let clustersResponse;
163
+ if (getFromCache(`showArchived=${showArchivedClusters}input=${search}p=${page}`)) {
164
+ clustersResponse = getFromCache(`showArchived=${showArchivedClusters}input=${search}p=${page}`);
165
+ }
166
+ else {
167
+ if (abortControllerRef.current !== undefined) {
168
+ // Cancel the previous request
169
+ abortControllerRef.current.abort();
170
+ }
171
+ // recreate a new AbortController for each call
172
+ let controller = new AbortController();
173
+ abortControllerRef.current = controller;
174
+ // query language: https://github.com/yaacov/tree-search-language
175
+ clustersResponse = yield cloud.getAccountClustersSubscription({
176
+ order: 'display_name asc',
177
+ page,
178
+ size: PER_PAGE,
179
+ search: `${showArchivedClusters ? '' : "status!='Archived'"} ${search && !showArchivedClusters ? 'AND' : ''} ${search
180
+ ? `(external_cluster_id ILIKE '%${search}%' OR display_name ILIKE '%${search}%' OR console_url ILIKE '%${search}%')`
181
+ : ''}`,
182
+ fields: 'external_cluster_id,display_name,status,metrics.openshift_version,console_url',
183
+ }, controller.signal);
184
+ setInCache(`showArchived=${showArchivedClusters}input=${search}p=${page}`, clustersResponse);
185
+ }
186
+ setIsFetchingClusters(false);
159
187
  const items = clustersResponse.items
160
188
  .filter((c) => !isEmpty(c.external_cluster_id))
161
189
  .map((item) => {
162
190
  var _a, _b;
163
191
  return ({
164
- display_name: getDisplayNameForCluster(item),
192
+ display_name: item.display_name,
165
193
  external_cluster_id: item.external_cluster_id,
166
194
  openshift_version: ((_b = (_a = item === null || item === void 0 ? void 0 : item.metrics) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.openshift_version) || '',
195
+ console_url: (item === null || item === void 0 ? void 0 : item.console_url) && (item === null || item === void 0 ? void 0 : item.console_url) !== null
196
+ ? item.console_url.split('.').slice(4).join('.')
197
+ : '',
167
198
  });
168
199
  });
169
- try {
170
- // old api has dns info
171
- // new api doesn't have dns info but we can exclude archived clusters
172
- // call old api get all clusters and call new api get limitted number of clusters
173
- // then add dns info to the new api response
174
- const promiseArray = clustersResponse.items.map((cluster) => cloud.getAccountClusters({
175
- order: 'display_name asc',
176
- search: `external_id='${cluster.external_cluster_id}' OR display_name='${cluster.external_cluster_id}'`,
177
- }, controller.signal));
178
- const oldApiResponse = yield Promise.allSettled(promiseArray);
179
- oldApiResponse.forEach((response) => {
180
- var _a, _b;
181
- if (response.status === 'fulfilled' && ((_b = (_a = response.value) === null || _a === void 0 ? void 0 : _a.items) === null || _b === void 0 ? void 0 : _b[0].dns)) {
182
- var index = findIndex(items, { external_cluster_id: response.value.items[0].external_id });
183
- items[index] = Object.assign(Object.assign({}, items[index]), { dns: response.value.items[0].dns });
184
- }
185
- });
186
- }
187
- catch (e) {
188
- // silently fails
189
- }
190
- setIsFetchingClusters(false);
191
200
  return {
192
201
  items,
193
202
  totalResult: items.length,
@@ -201,17 +210,37 @@ function OpenshiftDropdownV4(props) {
201
210
  return { items: [], totalResult: 0, page: 0, total: 0 };
202
211
  }
203
212
  });
204
- // need to get clusters on load
213
+ // when user visits case detail or clusterId comes from url,
214
+ // we have clusterId but need to get display name
215
+ useEffect(() => {
216
+ const getClusterDetails = () => __awaiter(this, void 0, void 0, function* () {
217
+ if (props.openshiftClusterIDState &&
218
+ props.openshiftClusterIDState !== 'dont-have-id' &&
219
+ props.openshiftClusterIDState !== 'v3-cluster' &&
220
+ isEmpty(props.openshiftDisplayName)) {
221
+ const fetchedCluster = yield fetchAClusterIdDetails(props.openshiftClusterIDState);
222
+ props.onClusterIdStateUpdate(Object.assign(Object.assign({}, fetchedCluster), { display_name: getDisplayNameForCluster(fetchedCluster) }));
223
+ }
224
+ });
225
+ getClusterDetails();
226
+ // no dependency here as we want to run this once on load
227
+ // eslint-disable-next-line react-hooks/exhaustive-deps
228
+ }, []);
229
+ // need to get clusters when user opens the dropdown
230
+ // as the api response is cached np extra call is made on open/close
205
231
  // added observing props.isV4 because re-render
206
232
  // is needed when user on overview page changing version
207
233
  useEffect(() => {
234
+ if (!isOpen)
235
+ return;
208
236
  let isUnmounted = false;
209
237
  const fetchClusters = () => __awaiter(this, void 0, void 0, function* () {
238
+ setClustersSelectOptions(getClusterOptions([]));
210
239
  const fetchedClusters = yield fetchAccountClusters(inputVal);
211
240
  if (!isUnmounted) {
212
241
  setClustersRawResponse(fetchedClusters.items);
213
242
  setTotalResultsNo(fetchedClusters.total);
214
- setClustersSelectOptions(getClusterOptions(fetchedClusters.items));
243
+ setClustersSelectOptions(getClusterOptions(fetchedClusters.items) || []);
215
244
  }
216
245
  });
217
246
  fetchClusters();
@@ -219,7 +248,7 @@ function OpenshiftDropdownV4(props) {
219
248
  isUnmounted = true;
220
249
  };
221
250
  // eslint-disable-next-line react-hooks/exhaustive-deps
222
- }, [props.isV4, showArchivedClusters]);
251
+ }, [props.isV4, showArchivedClusters, isOpen, inputVal]);
223
252
  useEffect(() => {
224
253
  if (props.isClusterIdInvalid) {
225
254
  setValidated('error');
@@ -228,20 +257,29 @@ function OpenshiftDropdownV4(props) {
228
257
  setValidated('default');
229
258
  }
230
259
  }, [props.isClusterIdInvalid]);
260
+ // when user type or paste a clusterId we land here
231
261
  const onTypeaheadInputChanged = (input) => __awaiter(this, void 0, void 0, function* () {
232
262
  setInputVal(input);
233
- props.onClusterIdStateUpdate(createState(input, input));
234
- const fetchedClusters = yield fetchAccountClusters(input);
235
- setClustersRawResponse(fetchedClusters.items);
236
- setTotalResultsNo(fetchedClusters.total);
237
- setClustersSelectOptions(getClusterOptions(fetchedClusters.items));
263
+ if (getIsClusterIdInvalid(input)) {
264
+ const fetchedClusters = yield fetchAccountClusters(input);
265
+ setClustersRawResponse(fetchedClusters.items);
266
+ setTotalResultsNo(fetchedClusters.total);
267
+ setClustersSelectOptions(getClusterOptions(fetchedClusters.items));
268
+ props.onClusterIdStateUpdate({ external_cluster_id: input });
269
+ }
270
+ else {
271
+ // user paste a valid cluster id
272
+ const fetchedCluster = yield fetchAClusterIdDetails(input);
273
+ props.onClusterIdStateUpdate(fetchedCluster);
274
+ }
238
275
  });
276
+ const debounceFn = debounce(onTypeaheadInputChanged, 1000);
239
277
  const getSelectedItem = () => {
240
278
  if (!isEmpty(inputVal)) {
241
279
  return createState(props.openshiftClusterIDState, inputVal);
242
280
  }
243
281
  else {
244
- return createState(props.openshiftClusterIDState, getDisplayNameById(clustersRawResponse, props.openshiftClusterIDState, props.noClusterIdReasonExplanation));
282
+ return createState(props.openshiftClusterIDState, getDisplayName(props.openshiftClusterIDState, props.noClusterIdReasonExplanation || '', props.openshiftDisplayName || props.openshiftClusterIDState));
245
283
  }
246
284
  };
247
285
  const titleId = 'case-details-cluster-nickname-selector';
@@ -252,7 +290,7 @@ function OpenshiftDropdownV4(props) {
252
290
  React.createElement("span", { className: "form-required", "aria-hidden": true }, "*"),
253
291
  React.createElement(CaseOpenShiftPopover, null)),
254
292
  React.createElement("span", { id: titleId, hidden: true }, "Select a state"),
255
- React.createElement(Select, Object.assign({ variant: SelectVariant.typeahead, isDisabled: props.isDisabled, typeAheadAriaLabel: t('Search by Cluster ID and alias or manually enter your Cluster ID'), onToggle: onToggle, onSelect: onSelect, onClear: onDropdownClear, selections: getSelectedItem(), isOpen: isOpen, "aria-labelledby": titleId, placeholderText: t('Search by Cluster ID and alias or manually enter your Cluster ID'), hasInlineFilter: false, onTypeaheadInputChanged: onTypeaheadInputChanged, onFilter: () => undefined, validated: validated, "aria-invalid": props.isClusterIdInvalid, "aria-describedby": "clusterID-validate-helper", required: true }, (isFetchingClusters && { loadingVariant: 'spinner' }), (!isFetchingClusters &&
293
+ React.createElement(Select, Object.assign({ variant: SelectVariant.typeahead, isDisabled: props.isDisabled, typeAheadAriaLabel: t('Search by Cluster ID, alias, and domain or manually enter your Cluster ID'), onToggle: onToggle, onSelect: onSelect, onClear: onDropdownClear, selections: getSelectedItem(), isOpen: isOpen, "aria-labelledby": titleId, placeholderText: t('Search by Cluster ID, alias, and domain or manually enter your Cluster ID'), hasInlineFilter: false, onTypeaheadInputChanged: debounceFn, onFilter: () => undefined, validated: validated, "aria-invalid": props.isClusterIdInvalid, "aria-describedby": "clusterID-validate-helper", required: true }, (isFetchingClusters && { loadingVariant: 'spinner' }), (!isFetchingClusters &&
256
294
  clustersRawResponse.length < totalResultsNo && {
257
295
  loadingVariant: {
258
296
  text: 'Display additional results',
@@ -262,4 +300,4 @@ function OpenshiftDropdownV4(props) {
262
300
  React.createElement("div", { id: "clusterID-validate-helper", className: `form-instructions ${props.isClusterIdInvalid ? 'form-invalid' : ''}` }, props.clusterIdDropdownFormInstructions))));
263
301
  }
264
302
  OpenshiftDropdownV4.defaultProps = defaultProps;
265
- export { OpenshiftDropdownV4, fetchClusterIdDetails };
303
+ export { OpenshiftDropdownV4 };
@@ -3,6 +3,7 @@
3
3
  */
4
4
  import { FC } from 'react';
5
5
  interface IProps {
6
+ submitCaseAndNavigate: (isReSubmitting: boolean) => void;
6
7
  }
7
8
  declare const AlertToastWrapper: FC<IProps>;
8
9
  export default AlertToastWrapper;
@@ -1 +1 @@
1
- {"version":3,"file":"AlertToastWrapper.d.ts","sourceRoot":"","sources":["../../../../src/components/Recommendations/AlertToastWrapper.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAc,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAKlC,UAAU,MAAM;CAAG;AAEnB,QAAA,MAAM,iBAAiB,EAAE,EAAE,CAAC,MAAM,CAQjC,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
1
+ {"version":3,"file":"AlertToastWrapper.d.ts","sourceRoot":"","sources":["../../../../src/components/Recommendations/AlertToastWrapper.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAc,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAMlC,UAAU,MAAM;IACZ,qBAAqB,EAAE,CAAC,cAAc,EAAE,OAAO,KAAK,IAAI,CAAC;CAC5D;AAED,QAAA,MAAM,iBAAiB,EAAE,EAAE,CAAC,MAAM,CASjC,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
@@ -3,11 +3,13 @@
3
3
  */
4
4
  import { AlertGroup } from '@patternfly/react-core';
5
5
  import React from 'react';
6
+ import { ResubmitToast } from '../SubmitCase/ResubmitToast';
6
7
  import ClusterRecommendationToast from './ClusterRecommendationToast';
7
8
  import CriticalSolutionsToast from './CriticalSolutionsToast';
8
- const AlertToastWrapper = () => {
9
+ const AlertToastWrapper = ({ submitCaseAndNavigate }) => {
9
10
  return (React.createElement(AlertGroup, { isToast: true },
10
11
  React.createElement(CriticalSolutionsToast, null),
11
- React.createElement(ClusterRecommendationToast, null)));
12
+ React.createElement(ClusterRecommendationToast, null),
13
+ React.createElement(ResubmitToast, { submitCaseAndNavigate: submitCaseAndNavigate })));
12
14
  };
13
15
  export default AlertToastWrapper;
@@ -0,0 +1,9 @@
1
+ import { ISessionItem } from '@cee-eng/hydrajs/@types/api/pcm/troubleshootSession';
2
+ import { FC } from 'react';
3
+ interface IProps {
4
+ onRestore: (sessionItem: ISessionItem) => Promise<void>;
5
+ errorSession: ISessionItem;
6
+ }
7
+ export declare const RestoreLastSessionModal: FC<IProps>;
8
+ export {};
9
+ //# sourceMappingURL=RestoreLastSessionModal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RestoreLastSessionModal.d.ts","sourceRoot":"","sources":["../../../../src/components/SessionRestore/RestoreLastSessionModal.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,qDAAqD,CAAC;AAGnF,OAAc,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAMlC,UAAU,MAAM;IACZ,SAAS,EAAE,CAAC,WAAW,EAAE,YAAY,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD,YAAY,EAAE,YAAY,CAAC;CAC9B;AAED,eAAO,MAAM,uBAAuB,EAAE,EAAE,CAAC,MAAM,CA0D9C,CAAC"}