Skip to content

Commit 05930ce

Browse files
authored
Merge pull request #504 from vishnoianil/sync-dashboard
Use side toggle menu for dashboard cards
2 parents 41e439d + 62ed7b0 commit 05930ce

File tree

2 files changed

+162
-60
lines changed

2 files changed

+162
-60
lines changed

src/components/Dashboard/Github/dashboard.tsx

Lines changed: 76 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,23 @@ import {
2222
EmptyStateBody,
2323
EmptyStateFooter,
2424
EmptyStateActions,
25-
Stack,
26-
StackItem,
2725
Card,
2826
CardTitle,
2927
CardBody,
3028
Flex,
3129
FlexItem,
3230
Label,
33-
ModalBody
31+
ModalBody,
32+
CardHeader,
33+
Dropdown,
34+
MenuToggle,
35+
DropdownList,
36+
DropdownItem,
37+
MenuToggleElement,
38+
Gallery,
39+
GalleryItem
3440
} from '@patternfly/react-core';
35-
import { ExternalLinkAltIcon, OutlinedQuestionCircleIcon, GithubIcon } from '@patternfly/react-icons';
41+
import { ExternalLinkAltIcon, OutlinedQuestionCircleIcon, GithubIcon, EllipsisVIcon } from '@patternfly/react-icons';
3642

3743
const InstructLabLogo: React.FC = () => <Image src="/InstructLab-LogoFile-RGB-FullColor.svg" alt="InstructLab Logo" width={256} height={256} />;
3844

@@ -42,6 +48,7 @@ const DashboardGithub: React.FunctionComponent = () => {
4248
const [isFirstPullDone, setIsFirstPullDone] = React.useState<boolean>(false);
4349
const [isLoading, setIsLoading] = useState<boolean>(true);
4450
//const [error, setError] = React.useState<string | null>(null);
51+
const [isActionMenuOpen, setIsActionMenuOpen] = React.useState<{ [key: number]: boolean }>({});
4552
const router = useRouter();
4653

4754
const fetchAndSetPullRequests = React.useCallback(async () => {
@@ -96,6 +103,20 @@ const DashboardGithub: React.FunctionComponent = () => {
96103
return <div>Loading...</div>;
97104
}
98105

106+
const onActionMenuToggle = (id: number, isOpen: boolean) => {
107+
setIsActionMenuOpen((prevState) => ({
108+
...prevState,
109+
[id]: isOpen
110+
}));
111+
};
112+
113+
const onActionMenuSelect = (id: number) => {
114+
setIsActionMenuOpen((prevState) => ({
115+
...prevState,
116+
[id]: false
117+
}));
118+
};
119+
99120
return (
100121
<div>
101122
<PageBreadcrumb hasBodyWrapper={false}>
@@ -177,11 +198,57 @@ const DashboardGithub: React.FunctionComponent = () => {
177198
</EmptyStateFooter>
178199
</EmptyState>
179200
) : (
180-
<Stack hasGutter>
201+
<Gallery
202+
hasGutter
203+
minWidths={{
204+
md: '400px',
205+
lg: '450px',
206+
xl: '500px',
207+
'2xl': '600px'
208+
}}
209+
>
181210
{pullRequests.map((pr) => (
182-
<StackItem key={pr.number}>
211+
<GalleryItem key={pr.number}>
183212
<Card>
184-
<CardTitle>{pr.title}</CardTitle>
213+
<CardHeader
214+
actions={{
215+
actions: (
216+
<Dropdown
217+
onSelect={() => onActionMenuSelect(pr.number)}
218+
toggle={(toggleRef: React.Ref<MenuToggleElement>) => (
219+
<MenuToggle
220+
ref={toggleRef}
221+
isExpanded={isActionMenuOpen[pr.number] || false}
222+
onClick={() => onActionMenuToggle(pr.number, !isActionMenuOpen[pr.number])}
223+
variant="plain"
224+
aria-label="contribution action menu"
225+
icon={<EllipsisVIcon aria-hidden="true" />}
226+
/>
227+
)}
228+
isOpen={isActionMenuOpen[pr.number] || false}
229+
onOpenChange={(isOpen: boolean) => onActionMenuToggle(pr.number, isOpen)}
230+
>
231+
<DropdownList>
232+
<DropdownItem key="view-pr" to={pr.html_url} target="_blank" rel="noopener noreferrer">
233+
View PR
234+
</DropdownItem>
235+
{pr.state === 'open' && (
236+
<DropdownItem key="edit-contribution" onClick={() => handleEditClick(pr)}>
237+
Edit Contribution
238+
</DropdownItem>
239+
)}
240+
{pr.state === 'closed' && (
241+
<DropdownItem key="edit-contribution" isDisabled>
242+
Edit Contribution
243+
</DropdownItem>
244+
)}
245+
</DropdownList>
246+
</Dropdown>
247+
)
248+
}}
249+
>
250+
<CardTitle>{pr.title}</CardTitle>
251+
</CardHeader>
185252
<CardBody>
186253
<Flex justifyContent={{ default: 'justifyContentSpaceBetween' }}>
187254
<FlexItem>State: {pr.state}</FlexItem>
@@ -194,24 +261,12 @@ const DashboardGithub: React.FunctionComponent = () => {
194261
</Label>
195262
))}
196263
</FlexItem>
197-
<FlexItem alignSelf={{ default: 'alignSelfFlexEnd' }} flex={{ default: 'flexNone' }}>
198-
<Button variant="secondary" component="a" href={pr.html_url} target="_blank" rel="noopener noreferrer">
199-
View PR
200-
</Button>
201-
</FlexItem>
202-
<FlexItem alignSelf={{ default: 'alignSelfFlexEnd' }} flex={{ default: 'flexNone' }}>
203-
{pr.state === 'open' && (
204-
<Button variant="primary" onClick={() => handleEditClick(pr)}>
205-
Edit
206-
</Button>
207-
)}
208-
</FlexItem>
209264
</Flex>
210265
</CardBody>
211266
</Card>
212-
</StackItem>
267+
</GalleryItem>
213268
))}
214-
</Stack>
269+
</Gallery>
215270
)}
216271
</PageSection>
217272
</div>

src/components/Dashboard/Native/dashboard.tsx

Lines changed: 86 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -22,28 +22,26 @@ import {
2222
EmptyStateBody,
2323
EmptyStateFooter,
2424
EmptyStateActions,
25-
Stack,
26-
StackItem,
2725
Card,
2826
CardBody,
2927
Flex,
3028
FlexItem,
31-
Tooltip,
3229
Modal,
3330
ModalVariant,
3431
ModalBody,
3532
ModalFooter,
36-
ModalHeader
33+
ModalHeader,
34+
DropdownItem,
35+
Dropdown,
36+
MenuToggleElement,
37+
MenuToggle,
38+
DropdownList,
39+
CardHeader,
40+
CardTitle,
41+
Gallery,
42+
GalleryItem
3743
} from '@patternfly/react-core';
38-
import {
39-
ExternalLinkAltIcon,
40-
OutlinedQuestionCircleIcon,
41-
GithubIcon,
42-
CatalogIcon,
43-
PencilAltIcon,
44-
UploadIcon,
45-
TrashIcon
46-
} from '@patternfly/react-icons';
44+
import { ExternalLinkAltIcon, OutlinedQuestionCircleIcon, GithubIcon, EllipsisVIcon } from '@patternfly/react-icons';
4745
import { ExpandableSection } from '@patternfly/react-core/dist/esm/components/ExpandableSection/ExpandableSection';
4846
import { v4 as uuidv4 } from 'uuid';
4947

@@ -68,10 +66,11 @@ const DashboardNative: React.FunctionComponent = () => {
6866
const [isLoading, setIsLoading] = React.useState<boolean>(true);
6967
const [mergeStatus] = React.useState<{ branch: string; message: string; success: boolean } | null>(null);
7068
const [diffData, setDiffData] = React.useState<{ branch: string; changes: ChangeData[] } | null>(null);
71-
const [isModalOpen, setIsModalOpen] = React.useState<boolean>(false);
72-
const [alerts, setAlerts] = React.useState<AlertItem[]>([]);
69+
const [isActionMenuOpen, setIsActionMenuOpen] = React.useState<{ [key: string]: boolean }>({});
70+
const [isChangeModalOpen, setIsChangeModalOpen] = React.useState<boolean>(false);
7371
const [isDeleteModalOpen, setIsDeleteModalOpen] = React.useState(false);
7472
const [isPublishModalOpen, setIsPublishModalOpen] = React.useState(false);
73+
const [alerts, setAlerts] = React.useState<AlertItem[]>([]);
7574
const [selectedBranch, setSelectedBranch] = React.useState<string | null>(null);
7675
const [isPublishing, setIsPublishing] = React.useState(false);
7776
const [expandedFiles, setExpandedFiles] = React.useState<Record<string, boolean>>({});
@@ -171,7 +170,7 @@ const DashboardNative: React.FunctionComponent = () => {
171170
const result = await response.json();
172171
if (response.ok) {
173172
setDiffData({ branch: branchName, changes: result.changes });
174-
setIsModalOpen(true);
173+
setIsChangeModalOpen(true);
175174
} else {
176175
console.error('Failed to get branch changes:', result.error);
177176
}
@@ -286,6 +285,20 @@ const DashboardNative: React.FunctionComponent = () => {
286285
}));
287286
};
288287

288+
const onActionMenuToggle = (id: string, isOpen: boolean) => {
289+
setIsActionMenuOpen((prevState) => ({
290+
...prevState,
291+
[id]: isOpen
292+
}));
293+
};
294+
295+
const onActionMenuSelect = (id: string) => {
296+
setIsActionMenuOpen((prevState) => ({
297+
...prevState,
298+
[id]: false
299+
}));
300+
};
301+
289302
return (
290303
<div>
291304
<PageBreadcrumb hasBodyWrapper={false}>
@@ -330,6 +343,7 @@ const DashboardNative: React.FunctionComponent = () => {
330343
/>
331344
))}
332345
</AlertGroup>
346+
333347
{isLoading ? (
334348
<Spinner size="lg" />
335349
) : branches.length === 0 ? (
@@ -370,41 +384,73 @@ const DashboardNative: React.FunctionComponent = () => {
370384
</EmptyStateFooter>
371385
</EmptyState>
372386
) : (
373-
<Stack hasGutter>
387+
<Gallery
388+
hasGutter
389+
minWidths={{
390+
md: '400px',
391+
lg: '450px',
392+
xl: '500px',
393+
'2xl': '600px'
394+
}}
395+
>
374396
{branches.map((branch) => (
375-
<StackItem key={branch.name}>
376-
<Card>
397+
<GalleryItem key={branch.name}>
398+
<Card key={branch.name}>
399+
<CardHeader
400+
actions={{
401+
actions: (
402+
<Dropdown
403+
onSelect={() => onActionMenuSelect(branch.name)}
404+
toggle={(toggleRef: React.Ref<MenuToggleElement>) => (
405+
<MenuToggle
406+
ref={toggleRef}
407+
isExpanded={isActionMenuOpen[branch.name] || false}
408+
onClick={() => onActionMenuToggle(branch.name, !isActionMenuOpen[branch.name])}
409+
variant="plain"
410+
aria-label="contribution action menu"
411+
icon={<EllipsisVIcon aria-hidden="true" />}
412+
/>
413+
)}
414+
isOpen={isActionMenuOpen[branch.name] || false}
415+
onOpenChange={(isOpen: boolean) => onActionMenuToggle(branch.name, isOpen)}
416+
>
417+
<DropdownList>
418+
<DropdownItem key="show-changes" onClick={() => handleShowChanges(branch.name)}>
419+
Show Changes
420+
</DropdownItem>
421+
<DropdownItem key="edit-contribution" onClick={() => handleEditContribution(branch.name)}>
422+
Edit Contribution
423+
</DropdownItem>
424+
<DropdownItem key="publish-contribution" onClick={() => handlePublishContribution(branch.name)}>
425+
Publish Contribution
426+
</DropdownItem>
427+
<DropdownItem key="delete-contribution" onClick={() => handleDeleteContribution(branch.name)}>
428+
Delete Contribution
429+
</DropdownItem>
430+
</DropdownList>
431+
</Dropdown>
432+
)
433+
}}
434+
>
435+
<CardTitle>
436+
<b>{branch.message}</b>
437+
</CardTitle>
438+
</CardHeader>
377439
<CardBody>
378440
<Flex justifyContent={{ default: 'justifyContentSpaceBetween' }}>
379441
<FlexItem>
380442
Branch Name: {branch.name}
381443
<br />
382-
Contribution Title: <b>{branch.message}</b>
383-
<br />
384444
Author: {branch.author} {' '}
385445
<br />
386446
Created on: {formatDateTime(branch.creationDate)}
387447
</FlexItem>
388-
<FlexItem align={{ default: 'alignRight' }}>
389-
<Tooltip aria="none" aria-live="polite" content={<div>Show Changes</div>}>
390-
<Button icon={<CatalogIcon />} variant="plain" aria-label="show" onClick={() => handleShowChanges(branch.name)} />
391-
</Tooltip>
392-
<Tooltip aria="none" aria-live="polite" content={<div>Edit Contribution</div>}>
393-
<Button icon={<PencilAltIcon />} variant="plain" aria-label="edit" onClick={() => handleEditContribution(branch.name)} />
394-
</Tooltip>
395-
<Tooltip aria="none" aria-live="polite" content={<div>Publish Changes</div>}>
396-
<Button icon={<UploadIcon />} variant="plain" aria-label="publish" onClick={() => handlePublishContribution(branch.name)} />
397-
</Tooltip>
398-
<Tooltip aria="none" aria-live="polite" content={<div>Delete</div>}>
399-
<Button icon={<TrashIcon />} variant="plain" aria-label="delete" onClick={() => handleDeleteContribution(branch.name)} />
400-
</Tooltip>
401-
</FlexItem>
402448
</Flex>
403449
</CardBody>
404450
</Card>
405-
</StackItem>
451+
</GalleryItem>
406452
))}
407-
</Stack>
453+
</Gallery>
408454
)}
409455

410456
{mergeStatus && (
@@ -416,8 +462,8 @@ const DashboardNative: React.FunctionComponent = () => {
416462
<Modal
417463
variant={ModalVariant.medium}
418464
title={`Files Contained in Branch: ${diffData?.branch}`}
419-
isOpen={isModalOpen}
420-
onClose={() => setIsModalOpen(false)}
465+
isOpen={isChangeModalOpen}
466+
onClose={() => setIsChangeModalOpen(false)}
421467
aria-labelledby="changes-contribution-modal-title"
422468
aria-describedby="changes-contribution-body-variant"
423469
>
@@ -459,6 +505,7 @@ const DashboardNative: React.FunctionComponent = () => {
459505
)}
460506
</ModalBody>
461507
</Modal>
508+
462509
<Modal
463510
variant={ModalVariant.small}
464511
title="Deleting Contribution"

0 commit comments

Comments
 (0)