Skip to content

Commit 4e2eea8

Browse files
authored
Merge pull request #1446 from qube-rt/display-git-push-actions
feat: Add action summary to push view
2 parents 232980a + 01c544f commit 4e2eea8

4 files changed

Lines changed: 402 additions & 45 deletions

File tree

src/ui/components/CustomTabs/CustomTabs.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import CardBody from '../Card/CardBody';
2424
import CardHeader from '../Card/CardHeader';
2525
import styles from '../../assets/jss/material-dashboard-react/components/customTabsStyle';
2626
import { SvgIconProps } from '@material-ui/core';
27+
import Badge from '@material-ui/core/Badge';
2728

2829
const useStyles = makeStyles(styles as any);
2930

@@ -33,6 +34,7 @@ export type TabItem = {
3334
tabName: string;
3435
tabIcon?: React.ComponentType<SvgIconProps>;
3536
tabContent: React.ReactNode;
37+
badge?: number;
3638
};
3739

3840
interface CustomTabsProps {
@@ -81,6 +83,13 @@ const CustomTabs: React.FC<CustomTabsProps> = ({
8183
>
8284
{tabs.map((prop, key) => {
8385
const icon = prop.tabIcon ? { icon: <prop.tabIcon /> } : {};
86+
const label = prop.badge ? (
87+
<Badge badgeContent={prop.badge} color='error'>
88+
{prop.tabName}
89+
</Badge>
90+
) : (
91+
prop.tabName
92+
);
8493
return (
8594
<Tab
8695
classes={{
@@ -89,7 +98,7 @@ const CustomTabs: React.FC<CustomTabsProps> = ({
8998
wrapper: classes.tabWrapper,
9099
}}
91100
key={key}
92-
label={prop.tabName}
101+
label={label}
93102
{...icon}
94103
/>
95104
);

src/ui/views/PushDetails/PushDetails.tsx

Lines changed: 30 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -24,25 +24,24 @@ import Card from '../../components/Card/Card';
2424
import CardIcon from '../../components/Card/CardIcon';
2525
import CardBody from '../../components/Card/CardBody';
2626
import CardHeader, { CardHeaderColor } from '../../components/Card/CardHeader';
27-
import CardFooter from '../../components/Card/CardFooter';
2827
import Button from '../../components/CustomButtons/Button';
28+
import CustomTabs from '../../components/CustomTabs/CustomTabs';
29+
import CommitDataTable from './components/CommitDataTable';
2930
import Diff from './components/Diff';
31+
import StepsTimeline from './components/StepsTimeline';
3032
import Attestation from './components/Attestation';
3133
import AttestationInfo from './components/AttestationInfo';
3234
import RejectionInfo from './components/RejectionInfo';
3335
import Reject from './components/Reject';
34-
import Table from '@material-ui/core/Table';
35-
import TableBody from '@material-ui/core/TableBody';
36-
import TableHead from '@material-ui/core/TableHead';
37-
import TableRow from '@material-ui/core/TableRow';
38-
import TableCell from '@material-ui/core/TableCell';
3936
import { getPush, authorisePush, rejectPush, cancelPush } from '../../services/git-push';
4037
import type { ServiceResult } from '../../services/errors';
41-
import { CheckCircle, Visibility, Cancel, Block } from '@material-ui/icons';
38+
import { CheckCircle, Visibility, Cancel, Block, List as ListIcon } from '@material-ui/icons';
39+
import CodeIcon from '@material-ui/icons/Code';
40+
import TimelineIcon from '@material-ui/icons/Timeline';
4241
import Snackbar from '@material-ui/core/Snackbar';
4342
import { PushActionView } from '../../types';
4443
import { trimPrefixRefsHeads, trimTrailingDotGit } from '../../../db/helper';
45-
import { generateEmailLink, getGitProvider } from '../../utils';
44+
import { getGitProvider } from '../../utils';
4645

4746
const Dashboard: React.FC = () => {
4847
const { id } = useParams<{ id: string }>();
@@ -115,6 +114,8 @@ const Dashboard: React.FC = () => {
115114
if (isError) throw new Error(message || 'Something went wrong ...');
116115
if (!push) return <div>No push data found</div>;
117116

117+
const errorCount = push.steps?.filter((step) => step.error).length ?? 0;
118+
118119
let headerData: { title: string; color: CardHeaderColor } = {
119120
title: 'Pending',
120121
color: 'warning',
@@ -249,44 +250,29 @@ const Dashboard: React.FC = () => {
249250
</GridContainer>
250251
</CardBody>
251252
</Card>
252-
<Card>
253-
<CardHeader color={headerData.color} stats icon>
254-
<h3>{headerData.title}</h3>
255-
</CardHeader>
256-
<CardBody>
257-
<Table>
258-
<TableHead>
259-
<TableRow>
260-
<TableCell>Timestamp</TableCell>
261-
<TableCell>Committer</TableCell>
262-
<TableCell>Author</TableCell>
263-
<TableCell>Message</TableCell>
264-
</TableRow>
265-
</TableHead>
266-
<TableBody>
267-
{push.commitData?.map((c) => (
268-
<TableRow key={c.commitTimestamp}>
269-
<TableCell>
270-
{moment.unix(Number(c.commitTimestamp || 0)).toString()}
271-
</TableCell>
272-
<TableCell>{generateEmailLink(c.committer, c.committerEmail)}</TableCell>
273-
<TableCell>{generateEmailLink(c.author, c.authorEmail)}</TableCell>
274-
<TableCell>{c.message}</TableCell>
275-
</TableRow>
276-
))}
277-
</TableBody>
278-
</Table>
279-
</CardBody>
280-
</Card>
281253
</GridItem>
282254
<GridItem xs={12} sm={12} md={12}>
283-
<Card>
284-
<CardHeader />
285-
<CardBody>
286-
<Diff diff={push.diff.content} />
287-
</CardBody>
288-
<CardFooter />
289-
</Card>
255+
<CustomTabs
256+
headerColor='primary'
257+
tabs={[
258+
{
259+
tabName: 'Commits',
260+
tabIcon: ListIcon,
261+
tabContent: <CommitDataTable commitData={push.commitData || []} />,
262+
},
263+
{
264+
tabName: 'Changes',
265+
tabIcon: CodeIcon,
266+
tabContent: <Diff diff={push.diff?.content || ''} />,
267+
},
268+
{
269+
tabName: 'Steps',
270+
tabIcon: TimelineIcon,
271+
tabContent: <StepsTimeline steps={push.steps ?? []} />,
272+
badge: errorCount > 0 ? errorCount : undefined,
273+
},
274+
]}
275+
/>
290276
</GridItem>
291277
</GridContainer>
292278
</div>
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/**
2+
* Copyright 2026 GitProxy Contributors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import React from 'react';
18+
import moment from 'moment';
19+
import Table from '@material-ui/core/Table';
20+
import TableBody from '@material-ui/core/TableBody';
21+
import TableHead from '@material-ui/core/TableHead';
22+
import TableRow from '@material-ui/core/TableRow';
23+
import TableCell from '@material-ui/core/TableCell';
24+
import { generateEmailLink } from '../../../utils';
25+
import { CommitData } from '../../../../proxy/processors/types';
26+
27+
interface CommitDataTableProps {
28+
commitData: CommitData[];
29+
}
30+
31+
const CommitDataTable: React.FC<CommitDataTableProps> = ({ commitData }) => {
32+
if (commitData.length === 0) {
33+
return <p>No commits found for this push.</p>;
34+
}
35+
36+
return (
37+
<Table>
38+
<TableHead>
39+
<TableRow>
40+
<TableCell>Timestamp</TableCell>
41+
<TableCell>Committer</TableCell>
42+
<TableCell>Author</TableCell>
43+
<TableCell>Message</TableCell>
44+
</TableRow>
45+
</TableHead>
46+
<TableBody>
47+
{commitData.map((c) => (
48+
<TableRow key={c.commitTimestamp}>
49+
<TableCell>{moment.unix(Number(c.commitTimestamp || 0)).toString()}</TableCell>
50+
<TableCell>{generateEmailLink(c.committer, c.committerEmail)}</TableCell>
51+
<TableCell>{generateEmailLink(c.author, c.authorEmail)}</TableCell>
52+
<TableCell>{c.message}</TableCell>
53+
</TableRow>
54+
))}
55+
</TableBody>
56+
</Table>
57+
);
58+
};
59+
60+
export default CommitDataTable;

0 commit comments

Comments
 (0)