Skip to content

Commit 79d455a

Browse files
authored
RHCLOUD-37312 - support case help panel tab (#121)
* support case help panel tab * add pagination and sort cases by lastModified * add text wrapping to row
1 parent 4deb09b commit 79d455a

File tree

1 file changed

+206
-20
lines changed

1 file changed

+206
-20
lines changed

src/components/HelpPanel/HelpPanelTabs/SupportPanel.tsx

Lines changed: 206 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,211 @@
1-
import React from 'react';
2-
import { TextInput } from '@patternfly/react-core';
3-
4-
const SupportPanel = ({
5-
setNewActionTitle,
6-
}: {
7-
setNewActionTitle: (title: string) => void;
8-
}) => {
9-
const [searchText, setSearchText] = React.useState('');
10-
const handleTextInputChange = (_e: unknown, value: string) => {
11-
setSearchText(value);
12-
setNewActionTitle(value);
1+
import React, { useEffect, useState } from 'react';
2+
import {
3+
Button,
4+
Content,
5+
ContentVariants,
6+
EmptyState,
7+
EmptyStateBody,
8+
EmptyStateVariant,
9+
Icon,
10+
Pagination,
11+
Stack,
12+
StackItem,
13+
Title,
14+
} from '@patternfly/react-core';
15+
import useChrome from '@redhat-cloud-services/frontend-components/useChrome';
16+
import SkeletonTable from '@redhat-cloud-services/frontend-components/SkeletonTable';
17+
import ExternalLinkAltIcon from '@patternfly/react-icons/dist/dynamic/icons/external-link-alt-icon';
18+
import HeadsetIcon from '@patternfly/react-icons/dist/dynamic/icons/headset-icon';
19+
import AttentionBellIcon from '@patternfly/react-icons/dist/dynamic/icons/attention-bell-icon';
20+
import InProgressIcon from '@patternfly/react-icons/dist/dynamic/icons/in-progress-icon';
21+
import {
22+
Table,
23+
TableVariant,
24+
Tbody,
25+
Td,
26+
Thead,
27+
Tr,
28+
} from '@patternfly/react-table';
29+
30+
const SUPPORT_CASE_URL =
31+
'https://access.redhat.com/support/cases/#/case/new/get-support?caseCreate=true';
32+
33+
type Case = {
34+
id: string;
35+
caseNumber: string;
36+
summary: string;
37+
lastModifiedDate: string;
38+
status: string;
39+
};
40+
41+
const columnNames = {
42+
summary: 'Title',
43+
status: 'Status',
44+
};
45+
46+
const statusTypes = {
47+
customerWaiting: 'Waiting on Customer',
48+
redHatWaiting: 'Waiting on Red Hat',
49+
};
50+
51+
export const statusIcons = (status: string) => {
52+
const statusMapper = {
53+
[statusTypes.customerWaiting]: (
54+
<Icon className="pf-t--global--icon--color--status--info--default">
55+
{status} <AttentionBellIcon />{' '}
56+
</Icon>
57+
),
58+
[statusTypes.redHatWaiting]: (
59+
<Icon>
60+
{status} <InProgressIcon />{' '}
61+
</Icon>
62+
),
63+
};
64+
return statusMapper[status] ?? '';
65+
};
66+
const SupportPanel: React.FunctionComponent = () => {
67+
const [cases, setCases] = useState<Case[]>([]);
68+
const chrome = useChrome();
69+
const [isLoading, setIsLoading] = useState(false);
70+
71+
const [page, setPage] = useState(1);
72+
const [perPage, setPerPage] = useState(20);
73+
74+
const onSetPage = (
75+
_event: React.MouseEvent | React.KeyboardEvent | MouseEvent,
76+
newPage: number
77+
) => {
78+
setPage(newPage);
79+
};
80+
81+
const onPerPageSelect = (
82+
_event: React.MouseEvent | React.KeyboardEvent | MouseEvent,
83+
newPerPage: number,
84+
newPage: number
85+
) => {
86+
setPerPage(newPerPage);
87+
setPage(newPage);
1388
};
89+
90+
const getUrl = (env: string) =>
91+
`https://api.access${
92+
env === 'stage' || env === 'frhStage' ? '.stage' : ''
93+
}.redhat.com/support/v1/cases/filter`;
94+
95+
const fetchSupportCases = async () => {
96+
const token = await chrome.auth.getToken();
97+
const user = await chrome.auth.getUser();
98+
const options = {
99+
method: 'POST',
100+
headers: {
101+
Authorization: `Bearer ${token}`,
102+
'Content-Type': 'application/json',
103+
Accept: 'application/json',
104+
},
105+
body: JSON.stringify({
106+
createdBySSOName: `${user?.identity.user?.username}`,
107+
}),
108+
};
109+
110+
try {
111+
const response = await fetch(getUrl(chrome.getEnvironment()), options);
112+
const { cases } = await response.json();
113+
114+
cases.sort(
115+
(a: { lastModifiedDate: number }, b: { lastModifiedDate: number }) =>
116+
new Date(b.lastModifiedDate).getTime() -
117+
new Date(a.lastModifiedDate).getTime()
118+
);
119+
120+
setCases(cases || []);
121+
setIsLoading(false);
122+
} catch (error) {
123+
console.error('Unable to fetch support cases', error);
124+
}
125+
};
126+
127+
useEffect(() => {
128+
setIsLoading(true);
129+
fetchSupportCases();
130+
}, []);
131+
14132
return (
15-
<div>
16-
<h3>My support cases</h3>
17-
<TextInput
18-
id="help-panel-support"
19-
value={searchText}
20-
onChange={handleTextInputChange}
21-
/>
22-
</div>
133+
<>
134+
{isLoading ? (
135+
<SkeletonTable rows={3} />
136+
) : cases.length === 0 ? (
137+
<EmptyState
138+
icon={HeadsetIcon}
139+
titleText={
140+
<Title headingLevel="h4" size="lg">
141+
No open support cases
142+
</Title>
143+
}
144+
variant={EmptyStateVariant.lg}
145+
>
146+
<EmptyStateBody>
147+
<Stack>
148+
<StackItem>
149+
We can&apos;t find any active support cases opened by you.
150+
</StackItem>
151+
</Stack>
152+
</EmptyStateBody>
153+
<Button
154+
variant="link"
155+
icon={<ExternalLinkAltIcon />}
156+
iconPosition="end"
157+
href={SUPPORT_CASE_URL}
158+
onClick={() => {
159+
window.open(SUPPORT_CASE_URL, '_blank');
160+
}}
161+
>
162+
Open a support case
163+
</Button>
164+
</EmptyState>
165+
) : (
166+
<>
167+
<Content component={ContentVariants.p}>
168+
Quickly see the status on all of your open support cases. To manage
169+
support cases or open a new one, visit the{' '}
170+
<Content
171+
component={ContentVariants.a}
172+
isVisitedLink
173+
href={SUPPORT_CASE_URL}
174+
>
175+
Customer Portal
176+
</Content>
177+
</Content>
178+
<Table variant={TableVariant.compact}>
179+
<Thead>My open support cases ({cases.length})</Thead>
180+
<Tbody>
181+
{cases.map((c) => (
182+
<Tr key={c.id}>
183+
<Td dataLabel={columnNames.summary} modifier="wrap">
184+
<a
185+
href={`https://access.redhat.com/support/cases/#/case/${c.caseNumber}`}
186+
>
187+
{c.summary} <ExternalLinkAltIcon key="icon" />
188+
</a>
189+
</Td>
190+
<Td dataLabel={columnNames.status}>
191+
{statusIcons(c.status)}
192+
</Td>
193+
</Tr>
194+
))}
195+
</Tbody>
196+
</Table>
197+
<Pagination
198+
itemCount={cases.length}
199+
perPage={perPage}
200+
page={page}
201+
onSetPage={onSetPage}
202+
widgetId="compact-example"
203+
onPerPageSelect={onPerPageSelect}
204+
isCompact
205+
/>
206+
</>
207+
)}
208+
</>
23209
);
24210
};
25211

0 commit comments

Comments
 (0)