@rh-support/troubleshoot 2.2.46 → 2.2.48

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.
@@ -11,7 +11,7 @@ import { useCaseSelector } from '../../context/CaseContext';
11
11
  import { useCaseDetailsPageStateContext } from '../../context/CaseDetailsPageContext';
12
12
  import { PDFContext } from './PDFContainer';
13
13
  import CaseDetailsManagement from './Tabs/CaseDetails/CaseDetailsManagement';
14
- const CaseBugzilla = React.lazy(() => import(/* webpackChunkName: 'CaseBugzilla' */ './Tabs/CaseBugzilla/CaseBugzilla'));
14
+ const RelatedTickets = React.lazy(() => import(/* webpackChunkName: 'CaseBugzilla' */ './Tabs/RelatedTickets/RelatedTickets'));
15
15
  const CaseActionPlan = React.lazy(() => import(/* webpackChunkName: 'CaseActionPlan' */ './Tabs/CaseActionPlan/CaseActionPlan'));
16
16
  const CasePrivateNotes = React.lazy(() => import(/* webpackChunkName: 'CasePrivateNotes' */ './Tabs/CasePrivateNotes/CasePrivateNotes'));
17
17
  const CaseDiscussion = React.lazy(() => import(/* webpackChunkName: 'CaseDiscussion' */ './Tabs/CaseDiscussion/CaseDiscussion'));
@@ -30,16 +30,21 @@ export function CaseDetailsTabs(props) {
30
30
  const [activeTabKey, setActiveTabKey] = useState(0);
31
31
  const { caseDetailsPageState: { caseEscalations }, } = useCaseDetailsPageStateContext();
32
32
  const canSeePrivateNotes = ability.can(resourceActions.PATCH, resources.CASE_DETAILS, CaseDetailsFields.CASE_DETAILS_PRIVATE_NOTES_EDIT);
33
- const canSeeBugZillas = ability.can(resourceActions.PATCH, resources.CASE_DETAILS, CaseDetailsFields.CASE_DETAILS_BUGZILLAS);
33
+ // const canSeeBugZillas = ability.can(
34
+ // resourceActions.PATCH,
35
+ // resources.CASE_DETAILS,
36
+ // CaseDetailsFields.CASE_DETAILS_BUGZILLAS
37
+ // );
34
38
  const { isExportingPDF, pdfOption } = useContext(PDFContext);
35
39
  const canSeeRMEs = ability.can(resourceActions.PATCH, resources.CASE_DETAILS, CaseDetailsFields.CASE_DETAILS_RMES);
36
40
  const [selectedTab, setSelectedTab] = useState(CaseDetailsTabsEnum.DISCUSSION);
37
41
  const discussionTabRef = useRef(null);
38
- const bugZillaTabRef = useRef(null);
42
+ // const bugZillaTabRef: React.MutableRefObject<HTMLDivElement> = useRef(null);
39
43
  const managementTabRef = useRef(null);
40
44
  const privateNotesTabRef = useRef(null);
41
45
  const actionPlanTabRef = useRef(null);
42
46
  const escalationTabRef = useRef(null);
47
+ const relatedTicketsRef = useRef(null);
43
48
  const tabsToRender = [];
44
49
  const handleTabClick = (event, tabIndex) => {
45
50
  setActiveTabKey(tabIndex);
@@ -61,15 +66,14 @@ export function CaseDetailsTabs(props) {
61
66
  ref: managementTabRef,
62
67
  component: (React.createElement(CaseDetailsManagement, { caseNumber: caseNumber, routeProps: props.routeProps, tabRef: managementTabRef })),
63
68
  });
64
- canSeeBugZillas &&
65
- tabsToRender.push({
66
- 'data-tracking-id': 'case-details-bugzilla-tab',
67
- key: 'bugzillas',
68
- ref: bugZillaTabRef,
69
- routePath: 'bugzilla',
70
- title: CaseDetailsTabsEnum.BUGZILLA,
71
- component: React.createElement(CaseBugzilla, null),
72
- });
69
+ tabsToRender.push({
70
+ 'data-tracking-id': 'case-details-related-ticket-tab',
71
+ key: 'relatedTickets',
72
+ ref: relatedTicketsRef,
73
+ routePath: 'related-tickets',
74
+ title: CaseDetailsTabsEnum.RELATED_TICKETS,
75
+ component: React.createElement(RelatedTickets, null),
76
+ });
73
77
  tabsToRender.push({
74
78
  'data-tracking-id': 'case-details-actionplan-tab',
75
79
  key: 'action plan',
@@ -0,0 +1,3 @@
1
+ declare const RelatedTickets: () => JSX.Element;
2
+ export default RelatedTickets;
3
+ //# sourceMappingURL=RelatedTickets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RelatedTickets.d.ts","sourceRoot":"","sources":["../../../../../../src/components/CaseEditView/Tabs/RelatedTickets/RelatedTickets.tsx"],"names":[],"mappings":"AAsCA,QAAA,MAAM,cAAc,mBAsLnB,CAAC;AAEF,eAAe,cAAc,CAAC"}
@@ -0,0 +1,127 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { kase } from '@cee-eng/hydrajs';
11
+ import { Badge, EmptyState, EmptyStateHeader, EmptyStateIcon, EmptyStateVariant, Pagination, SearchInput, ToggleGroup, ToggleGroupItem, } from '@patternfly/react-core';
12
+ import CubesIcon from '@patternfly/react-icons/dist/esm/icons/cubes-icon';
13
+ import { Table, Tbody, Td, Th, Thead, Tr } from '@patternfly/react-table';
14
+ import { useFetch } from '@rh-support/components';
15
+ import { GlobalMetadataStateContext } from '@rh-support/react-context';
16
+ import isEqual from 'lodash/isEqual';
17
+ import React, { useContext, useEffect, useState } from 'react';
18
+ import { useTranslation } from 'react-i18next';
19
+ import { useCaseSelector } from '../../../../context/CaseContext';
20
+ const columnNames = {
21
+ id: 'Task ID',
22
+ type: 'Type',
23
+ status: 'Status',
24
+ title: 'Summary',
25
+ };
26
+ const RelatedTickets = () => {
27
+ const { globalMetadataState: { loggedInUserRights }, } = useContext(GlobalMetadataStateContext);
28
+ const [activeToggleKey, setActiveToggleKey] = useState('all');
29
+ const [currentPage, setCurrentPage] = useState(1);
30
+ const [itemsPerPage, setItemsPerPage] = useState(10);
31
+ const [searchQuery, setSearchQuery] = useState('');
32
+ const { caseNumber, bugzillaFetch } = useCaseSelector((state) => ({
33
+ caseNumber: state.caseDetails.caseNumber,
34
+ bugzillaFetch: state.caseDetails.bugzillas,
35
+ }), isEqual);
36
+ const { request: getCaseJiras } = useFetch(kase.fetchLinkedJiras, {
37
+ propgateErrors: true,
38
+ });
39
+ const [bugzillaData, setBugzillaData] = useState([]);
40
+ const [jiraData, setJiraData] = useState([]);
41
+ const { t } = useTranslation();
42
+ useEffect(() => {
43
+ setCurrentPage(1);
44
+ }, [searchQuery, activeToggleKey]);
45
+ useEffect(() => {
46
+ const fetchData = () => __awaiter(void 0, void 0, void 0, function* () {
47
+ try {
48
+ const bugzillaTransformed = bugzillaFetch.map((bugzilla) => ({
49
+ id: bugzilla.caseNumber,
50
+ type: 'Bugzilla',
51
+ link: bugzilla.bugzillaLink || '',
52
+ status: bugzilla.status || 'N/A',
53
+ title: bugzilla.summary || 'N/A',
54
+ date: new Date(bugzilla.linkedAt),
55
+ }));
56
+ setBugzillaData(bugzillaTransformed);
57
+ if (loggedInUserRights.data.isInternal()) {
58
+ const jiraResults = yield getCaseJiras(caseNumber);
59
+ const jiraTransformed = jiraResults.map((jira) => ({
60
+ id: jira.resourceKey,
61
+ type: 'Jira',
62
+ link: jira.resourceURL || '',
63
+ status: jira.status || 'N/A',
64
+ title: jira.title || 'N/A',
65
+ date: new Date(jira.createdDate),
66
+ }));
67
+ setJiraData(jiraTransformed);
68
+ }
69
+ }
70
+ catch (error) {
71
+ console.log(error);
72
+ }
73
+ });
74
+ fetchData();
75
+ // eslint-disable-next-line react-hooks/exhaustive-deps
76
+ }, [bugzillaFetch, caseNumber, loggedInUserRights.data]);
77
+ // don't add the jiradata into the combination if not internal
78
+ const combinedData = [...bugzillaData, ...(loggedInUserRights.data.isInternal() ? jiraData : [])].sort((a, b) => b.date.getTime() - a.date.getTime());
79
+ const filteredData = combinedData.filter((item) => {
80
+ const lowercasedQuery = searchQuery.toLowerCase();
81
+ if (searchQuery &&
82
+ !item.title.toLowerCase().includes(lowercasedQuery) &&
83
+ !item.id.toString().toLowerCase().includes(lowercasedQuery)) {
84
+ return false;
85
+ }
86
+ if (activeToggleKey === 'all')
87
+ return true;
88
+ if (activeToggleKey === 'bugzilla')
89
+ return item.type === 'Bugzilla';
90
+ if (activeToggleKey === 'jira')
91
+ return item.type === 'Jira' && loggedInUserRights.data.isInternal();
92
+ return true;
93
+ });
94
+ //pagination
95
+ const startIdx = (currentPage - 1) * itemsPerPage;
96
+ const endIdx = startIdx + itemsPerPage;
97
+ const displayData = filteredData.slice(startIdx, endIdx);
98
+ return (React.createElement("section", { className: "card card-white" },
99
+ (activeToggleKey === 'all' &&
100
+ (bugzillaData.length > 0 || (jiraData.length > 0 && loggedInUserRights.data.isInternal()))) ||
101
+ (activeToggleKey === 'bugzilla' && bugzillaData.length > 0) ||
102
+ (activeToggleKey === 'jira' && jiraData.length > 0 && loggedInUserRights.data.isInternal()) ? (React.createElement("div", { className: "related-ticket-search-input-container", id: "related-ticket-search-container" },
103
+ React.createElement(SearchInput, { className: "related-ticket-search-input", placeholder: t('Search by Task ID or Summary'), value: searchQuery, onChange: (event) => setSearchQuery(event.currentTarget.value), onClear: () => setSearchQuery('') }))) : null,
104
+ React.createElement(ToggleGroup, { "aria-label": "Toggle Group" },
105
+ React.createElement(ToggleGroupItem, { text: t('All'), isSelected: activeToggleKey === 'all', onChange: () => setActiveToggleKey('all'), "data-tracking-id": 'related-ticket-all' }),
106
+ React.createElement(ToggleGroupItem, { text: t('Bugzilla'), isSelected: activeToggleKey === 'bugzilla', onChange: () => setActiveToggleKey('bugzilla'), "data-tracking-id": 'related-ticket-bugzilla' }),
107
+ React.createElement(ToggleGroupItem, { text: t('Jira'), isSelected: activeToggleKey === 'jira', onChange: () => setActiveToggleKey('jira'), "data-tracking-id": 'related-ticket-jira' })),
108
+ filteredData.length > 0 ? (React.createElement(React.Fragment, null,
109
+ React.createElement(Table, { "aria-label": "Issue Table" },
110
+ React.createElement(Thead, null,
111
+ React.createElement(Tr, null,
112
+ React.createElement(Th, null, columnNames.id),
113
+ React.createElement(Th, null, columnNames.type),
114
+ React.createElement(Th, null, columnNames.status),
115
+ React.createElement(Th, null, columnNames.title))),
116
+ React.createElement(Tbody, null, displayData.map((item) => (React.createElement(Tr, { key: item.id },
117
+ React.createElement(Td, { dataLabel: columnNames.id }, item.link ? (React.createElement("a", { href: item.link, target: "_blank", rel: "noopener noreferrer" }, item.id)) : (item.id)),
118
+ React.createElement(Td, { dataLabel: columnNames.type }, item.type),
119
+ React.createElement(Td, { dataLabel: columnNames.status },
120
+ React.createElement(Badge, { isRead: true }, item.status)),
121
+ React.createElement(Td, { dataLabel: columnNames.title }, item.title)))))),
122
+ React.createElement("div", { className: "push-top" },
123
+ React.createElement(Pagination, { itemCount: filteredData.length, perPage: itemsPerPage, page: currentPage, onSetPage: (_, page) => setCurrentPage(page), onPerPageSelect: (_, perPage) => setItemsPerPage(perPage) })))) : (React.createElement("div", null,
124
+ React.createElement(EmptyState, { variant: EmptyStateVariant.full },
125
+ React.createElement(EmptyStateHeader, { titleText: t("There aren't any related tasks."), headingLevel: "h4", icon: React.createElement(EmptyStateIcon, { icon: CubesIcon }) }))))));
126
+ };
127
+ export default RelatedTickets;
@@ -5,7 +5,8 @@ export declare enum CaseDetailsTabsEnum {
5
5
  BUGZILLA = "Bugzilla",
6
6
  ACTION_PLAN = "Action plan",
7
7
  PRIVATE_NOTES = "Private Notes",
8
- ESCALATION = "Escalations"
8
+ ESCALATION = "Escalations",
9
+ RELATED_TICKETS = "Related Tickets"
9
10
  }
10
11
  export declare enum CaseStatusEnum {
11
12
  CLOSED = "Closed",
@@ -1 +1 @@
1
- {"version":3,"file":"caseDetailsConstants.d.ts","sourceRoot":"","sources":["../../../src/constants/caseDetailsConstants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,oCAAoC,yBAAyB,CAAC;AAE3E,oBAAY,mBAAmB;IAC3B,UAAU,eAAe;IACzB,UAAU,eAAe;IACzB,QAAQ,aAAa;IACrB,WAAW,gBAAgB;IAC3B,aAAa,kBAAkB;IAC/B,UAAU,gBAAgB;CAC7B;AAED,oBAAY,cAAc;IACtB,MAAM,WAAW;IACjB,mBAAmB,wBAAwB;IAC3C,iBAAiB,uBAAuB;CAC3C;AAED,eAAO,MAAM,0BAA0B,6DAA6D,CAAC;AAErG,eAAO,MAAM,mBAAmB,uCAAuC,CAAC;AAExE,eAAO,MAAM,kBAAkB,6BAA6B,CAAC;AAE7D,eAAO,MAAM,iBAAiB,8EAA8E,CAAC"}
1
+ {"version":3,"file":"caseDetailsConstants.d.ts","sourceRoot":"","sources":["../../../src/constants/caseDetailsConstants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,oCAAoC,yBAAyB,CAAC;AAE3E,oBAAY,mBAAmB;IAC3B,UAAU,eAAe;IACzB,UAAU,eAAe;IACzB,QAAQ,aAAa;IACrB,WAAW,gBAAgB;IAC3B,aAAa,kBAAkB;IAC/B,UAAU,gBAAgB;IAC1B,eAAe,oBAAoB;CACtC;AAED,oBAAY,cAAc;IACtB,MAAM,WAAW;IACjB,mBAAmB,wBAAwB;IAC3C,iBAAiB,uBAAuB;CAC3C;AAED,eAAO,MAAM,0BAA0B,6DAA6D,CAAC;AAErG,eAAO,MAAM,mBAAmB,uCAAuC,CAAC;AAExE,eAAO,MAAM,kBAAkB,6BAA6B,CAAC;AAE7D,eAAO,MAAM,iBAAiB,8EAA8E,CAAC"}
@@ -7,6 +7,7 @@ export var CaseDetailsTabsEnum;
7
7
  CaseDetailsTabsEnum["ACTION_PLAN"] = "Action plan";
8
8
  CaseDetailsTabsEnum["PRIVATE_NOTES"] = "Private Notes";
9
9
  CaseDetailsTabsEnum["ESCALATION"] = "Escalations";
10
+ CaseDetailsTabsEnum["RELATED_TICKETS"] = "Related Tickets";
10
11
  })(CaseDetailsTabsEnum || (CaseDetailsTabsEnum = {}));
11
12
  export var CaseStatusEnum;
12
13
  (function (CaseStatusEnum) {
@@ -600,3 +600,16 @@ ul.pf-v5-c-menu__list,
600
600
  .pf-v5-c-modal-box__title {
601
601
  margin-bottom: 0px;
602
602
  }
603
+
604
+ div.related-ticket-search-input-container#related-ticket-search-container {
605
+ float: right;
606
+ margin-bottom: 1rem;
607
+ }
608
+
609
+ .related-ticket-search-input {
610
+ width: 25rem;
611
+ }
612
+
613
+ button.pf-v5-c-toggle-group__button {
614
+ z-index: 1;
615
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rh-support/troubleshoot",
3
- "version": "2.2.46",
3
+ "version": "2.2.48",
4
4
  "publishConfig": {
5
5
  "access": "public",
6
6
  "registry": "https://registry.npmjs.org"
@@ -63,6 +63,7 @@
63
63
  "@patternfly/pfe-icon": "^1.12.3",
64
64
  "@patternfly/pfe-tabs": "1.12.3",
65
65
  "@patternfly/react-core": "5.1.1",
66
+ "@patternfly/react-table": "^5.1.1",
66
67
  "@progress/kendo-drawing": "^1.6.0",
67
68
  "@progress/kendo-react-pdf": "^3.12.0",
68
69
  "@rh-support/components": "2.1.27",
@@ -131,5 +132,5 @@
131
132
  "defaults and supports es6-module",
132
133
  "maintained node versions"
133
134
  ],
134
- "gitHead": "c70ed8ffa9b5dbe8abdd50e1549e92b8af2a6f27"
135
+ "gitHead": "8e4f76b9f341bc33c3cc44b081efb0ffe45f270a"
135
136
  }